我如何为尚未初始化的联合成员分配内存
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
是第一个来自 mem1
的 sizeof mem2
个字节:很可能是非 0。如果您希望类似联合的对象正确复制自身,通常需要将其包装在外部 struct
中,该外部 struct
添加一些 integral/enum 类型以跟踪联合的当前数据类型。包括您的 myUnion(wstring)
构造函数和析构函数在内的其他行为也存在缺陷。
在不调用未定义行为的情况下处理联合很棘手 - 你最好改用 boost::variant
。
我有两个成员的联盟。
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
是第一个来自 mem1
的 sizeof mem2
个字节:很可能是非 0。如果您希望类似联合的对象正确复制自身,通常需要将其包装在外部 struct
中,该外部 struct
添加一些 integral/enum 类型以跟踪联合的当前数据类型。包括您的 myUnion(wstring)
构造函数和析构函数在内的其他行为也存在缺陷。
在不调用未定义行为的情况下处理联合很棘手 - 你最好改用 boost::variant
。