std::string损坏的示例导致其值的作用域结束:
#include <bits/stdc++.h>
const int StackSize = 2137;
char stack[StackSize];
template <typename Type>
Type& push(Type value) {
char *ptr = (char*)&value;
std::copy_n(ptr, sizeof(Type), stack);
return *(Type*)stack;
}
template <typename Type>
Type& create(Type value) {
auto &var = push<Type>(value);
std::cout << "Should Be: " << var << 'n';
return var;
}
int main() {
auto &x = create<std::string>("Hello");
std::cout << "Is: " << x << 'n';
}
当我更改函数push以接收指针时,输出是正确的,但目前是"b">
我知道std::string有一个指向c字符串的指针,输出是不同的,因为函数push的参数在作用域结束时会被破坏。
但是为什么当我把指针传给push时,输出仍然是正确的呢?c字符串应在创建结束后销毁。
因为您正试图通过类似C的memcpy
/copy_n
将非平凡对象(std::string(存储在字符缓冲区中。
显然,这是失败的,因为你只是在那里逐字节地复制它,所以它的数据指针指向与临时value
字符串相同的位置,然后,当value
析构函数释放数据时(至少如果你的编译器不执行SSO(,你调用UB试图通过堆栈访问它。
我不清楚为您"工作"的代码看起来如何,但我想它只是通过在堆上分配字符串而不删除它来避免问题。
考虑一下在C++(即placement new
(中是如何实现的。