分配 Union 的字段
Assigning Union's fields
我创建了一个使用联合作为其字段的结构。这是一个小代码示例:
#include <iostream>
#include <string>
enum Type
{
STR,
INT
};
struct MyStruct
{
Type type;
union Value
{
std::string str;
int i;
Value(){}
~Value(){};
} value;
void setType(Type type)
{
this->type = type;
}
void setValue(const std::string& data)
{
this->value.str = data;
}
MyStruct(){}
~MyStruct(){}
};
int main()
{
MyStruct my;
my.setType(Type::STR);
my.setValue("Hallo");
std::cout << my.value.str << std::endl;
return 0;
}
Setting Value i got an error (Segmentation fault (core dumped)) 正确的方法是什么?谢谢!
尽管 C++11 确实允许您在联合中使用 classes,但它通常被认为是不好的做法,因为它是未定义行为的雷区。
如果您的联合体的构造函数没有构造作为 class 实例的联合体成员——就像您的示例代码一样——根据定义,class 实例永远不会被构造。
然后您的代码会尝试使用联盟的 class 成员。即它的运算符=。由于此 class 实例尚未构造,这将成为未定义的行为,从而导致您的崩溃。
在您的工会中坚持使用 POD
。减少悲伤。
小心。 union 中的非 POD 类型是自找麻烦。也就是说,这在 C++11 中是受支持的,前提是您最多只初始化一个成员。这意味着你必须改变事情的运作方式。
平凡地,要修复你的程序,你只需使用 placement new:
void setValue(const std::string& data)
{
new (&value.str) std::string(data);
}
但是现在,如果您以后想设置一个不同的成员,您将需要在字符串上使用放置删除。为此,您需要知道从那里开始有一个字符串。所以你不能轻易地将 setValue
与 setType
.
分开
一个选项(不是特别好)是:
private:
void setType( type ) {
// Destruct existing type
switch( this->type ) {
case STR:
value.str.~std::string();
break;
default:;
}
this->type = type;
}
public:
void setValue( const std::string& data )
{
setType( STR );
new (&value.str) std::string(data);
}
void setValue( int data )
{
setType( INT );
value.i = data;
}
并且不要忘记正确销毁 ~MyStruct
中的值。
我创建了一个使用联合作为其字段的结构。这是一个小代码示例:
#include <iostream>
#include <string>
enum Type
{
STR,
INT
};
struct MyStruct
{
Type type;
union Value
{
std::string str;
int i;
Value(){}
~Value(){};
} value;
void setType(Type type)
{
this->type = type;
}
void setValue(const std::string& data)
{
this->value.str = data;
}
MyStruct(){}
~MyStruct(){}
};
int main()
{
MyStruct my;
my.setType(Type::STR);
my.setValue("Hallo");
std::cout << my.value.str << std::endl;
return 0;
}
Setting Value i got an error (Segmentation fault (core dumped)) 正确的方法是什么?谢谢!
尽管 C++11 确实允许您在联合中使用 classes,但它通常被认为是不好的做法,因为它是未定义行为的雷区。
如果您的联合体的构造函数没有构造作为 class 实例的联合体成员——就像您的示例代码一样——根据定义,class 实例永远不会被构造。
然后您的代码会尝试使用联盟的 class 成员。即它的运算符=。由于此 class 实例尚未构造,这将成为未定义的行为,从而导致您的崩溃。
在您的工会中坚持使用 POD
。减少悲伤。
小心。 union 中的非 POD 类型是自找麻烦。也就是说,这在 C++11 中是受支持的,前提是您最多只初始化一个成员。这意味着你必须改变事情的运作方式。
平凡地,要修复你的程序,你只需使用 placement new:
void setValue(const std::string& data)
{
new (&value.str) std::string(data);
}
但是现在,如果您以后想设置一个不同的成员,您将需要在字符串上使用放置删除。为此,您需要知道从那里开始有一个字符串。所以你不能轻易地将 setValue
与 setType
.
一个选项(不是特别好)是:
private:
void setType( type ) {
// Destruct existing type
switch( this->type ) {
case STR:
value.str.~std::string();
break;
default:;
}
this->type = type;
}
public:
void setValue( const std::string& data )
{
setType( STR );
new (&value.str) std::string(data);
}
void setValue( int data )
{
setType( INT );
value.i = data;
}
并且不要忘记正确销毁 ~MyStruct
中的值。