我如何为尚未初始化的联合成员分配内存

how can i allocate memory for a union member that haven't been initialized

我有两个成员的联盟。

union myUnion {
    std::wstring mem1;
    int mem2;
    myUnion(std::wstring in){
        this->mem1 = in;
    }
    myUnion(int in){
        this->mem2 = in;
    }
    myUnion(const myUnion& in){
        if(this->mem2){
            this->mem2 = in.mem2;
        }else{
            this->mem1 = in.mem1;
        }
    }
};
//and then I make a vector out of the union:
std::vector<myUnion> unions;
//but when I try to push_back:
unions.push_back(L"A");

它很快就会出现 运行 时间错误: 0xC0000005:访问冲突写入位置 0xCCCCCCCC。 当我尝试调试这个程序时,我意识到 mem1 还没有分配内存。我真的不知道为什么会这样,我想知道我该如何解决它。

在 C++ 中,union 不是一种非常自然的数据类型,因为它并不真正适合整个 C++ 的构造函数和析构函数概念。当您在 C++ 中创建联合时,它不会为其任何可能的类型调用构造函数,因为它们将全部写在彼此之上。

所以这个构造函数

myUnion(std::wstring in){
    this->mem1 = in;
}

将崩溃,因为 this->mem1 作为字符串的生命周期尚未开始。您将不得不使用类似的方法,在该地址使用 placement new 调用 std::string ctor。稍后,如果更改数据类型,则必须确保记住在开始写入联合的不同字段之前也为 this->mem1 调用 dtor,否则会出现内存泄漏或损坏。

到目前为止,在 C++ 中做您想做的事情的更简单方法是使用像 boost::variant 这样的变体类型,它将为您处理所有样板文件和所有细节。 (如果您只使用没有 ctors 或 dtor 的普通类型,联合是可以的。)

typedef boost::variant<std::wstring, int> MyUnion;

std::vector<MyUnion> unions;

unions.push_back(L"A");

您的复制构造函数被破坏为...

if(this->mem2){

...对于除 0 以外的任何 mem2 值,return 都会为真,并且如果联合实际上是用字符串构造的,那么 mem2 是第一个来自 mem1sizeof mem2 个字节:很可能是非 0。如果您希望类似联合的对象正确复制自身,通常需要将其包装在外部 struct 中,该外部 struct 添加一些 integral/enum 类型以跟踪联合的当前数据类型。包括您的 myUnion(wstring) 构造函数和析构函数在内的其他行为也存在缺陷。

在不调用未定义行为的情况下处理联合很棘手 - 你最好改用 boost::variant