为什么std :: string在初始值被破坏后仍然有效?

时间:2018-08-06 12:16:08

标签: c++ pointers casting scope stdstring

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';
}

当我更改功能推送以接收指针时,输出正确,但当前为“ b”

我知道std :: string有一个指向c字符串的指针,并且输出是不同的,因为在作用域结束时函数push的参数被破坏了。

但是为什么当我传递指针进行推送时,输出仍然正确?创建结束后,应该销毁c字符串。

1 个答案:

答案 0 :(得分:2)

因为您正尝试通过类似C的memcpy / copy_n将非平凡的对象(std :: string)存储在char的缓冲区中。

显然,这失败了,因为您只是逐字节地将其复制到那里,因此其数据指针指向与临时value字符串相同的位置,然后,当数据被{{1 }}析构函数(至少在编译器不执行SSO的情况下),您会调用UB尝试通过堆栈访问它。

我不清楚您的“工作”代码看起来如何,但是我猜想它只是通过在堆上分配字符串而不是将其删除而避免了该问题。

考虑研究如何用C ++(即value)完成。