我有一个由两名成员组成的联盟。
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还没有分配内存。我真的不知道为什么会这样,我想知道如何解决它。
答案 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
代替。