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

时间:2015-08-31 03:37:01

标签: c++ memory vector unions

我有一个由两名成员组成的联盟。

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还没有分配内存。我真的不知道为什么会这样,我想知道如何解决它。

2 个答案:

答案 0 :(得分:3)

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

所以这个构造函数

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

将崩溃,因为this->mem1的生命周期尚未启动。你必须使用类似的东西,使用该地址的新位置来调用std::string ctor。稍后,如果更改数据类型,则必须确保在开始写入联合的其他字段之前记住调用this->mem1的dtor,否则会导致内存泄漏或损坏。< / p>

到目前为止,在C ++中尝试做的事情的简单方法是使用类似boost::variant的变体类型,它将为您处理所有样板和所有细节。 (如果你只使用没有ctors或dtors的琐碎类型,联盟是可以的。)

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

std::vector<MyUnion> unions;

unions.push_back(L"A");

答案 1 :(得分:1)

你的拷贝构造函数被打破为......

if(this->mem2){
对于mem2以外的任何0值,

...将返回true,如果联合实际上是用字符串构造的,则mem2是第一个sizeof mem2个字节来自mem1:很可能不是0。如果你想要一个类似联合的对象来正确地复制自己,你通常需要将它包装在一个外部struct中,它添加一些整数/枚举类型来跟踪联合的当前数据类型。包括你的myUnion(wstring)构造函数和析构函数在内的其他行为也存在缺陷。

在不调用未定义行为的情况下处理联盟非常棘手 - 您最好使用boost::variant代替。

相关问题