联合本身初始化后如何初始化联合成员?
How do you initialize a union member after the union itself was initialized?
如果可能的话,如何在联合本身初始化后初始化联合成员?
struct U_Keeper
{
U_Keeper() : x();
bool HoldingTypeU {true};
union
{
X x;
Y y;
};
};
void doSomething(){
U_Keeper uk;
doSomethingWithX(uk.x);
// set uk to Y mode and initialize uk.y
uk.HoldingTypeU = false;
};
假设 Y 是一个复杂的大型类型,需要进行初始化。你会怎么做?
我问的原因:我有一个这样的联合,其中“Y”将是 std::string
。当然,std::string
有一个赋值运算符,所以它的值可以稍后设置。但是我不确定 std::string
是否需要初始化,除了稍后是否会分配给它。也许当 std::string
被分配给它时,它建立在它已经拥有的数据之上:它覆盖了已经存在的数据,因此已经需要一个指向数据的有效指针。
如果联合成员是微不足道的,激活成员的传统方法是分配它:
uk.y = some_value;
如果成员不是平凡的(例如std::string
),那么您必须首先销毁当前活动的成员,然后使用 placement-new 初始化另一个成员:
uk.x.~X();
::new (&uk.y) Y /*parenthesised or braced init arguments here*/;
请注意,如果联合包含非平凡成员,则其所有特殊成员函数(默认构造函数除外)从析构函数到复制构造函数再到赋值运算符都将被隐式删除。因此,您需要为类似联合的 class 包装它定义那些。每个人都必须知道当前活跃的成员,并据此采取行动。
另请注意,析构函数不会隐式销毁联合成员,这与正常 class 不同,后者会在析构函数主体之后销毁成员。这必须像我上面显示的那样明确地完成。
P.S。标准库中有一个标准的标记联合:std::variant
。无需自己发明。
如果可能的话,如何在联合本身初始化后初始化联合成员?
struct U_Keeper
{
U_Keeper() : x();
bool HoldingTypeU {true};
union
{
X x;
Y y;
};
};
void doSomething(){
U_Keeper uk;
doSomethingWithX(uk.x);
// set uk to Y mode and initialize uk.y
uk.HoldingTypeU = false;
};
假设 Y 是一个复杂的大型类型,需要进行初始化。你会怎么做?
我问的原因:我有一个这样的联合,其中“Y”将是 std::string
。当然,std::string
有一个赋值运算符,所以它的值可以稍后设置。但是我不确定 std::string
是否需要初始化,除了稍后是否会分配给它。也许当 std::string
被分配给它时,它建立在它已经拥有的数据之上:它覆盖了已经存在的数据,因此已经需要一个指向数据的有效指针。
如果联合成员是微不足道的,激活成员的传统方法是分配它:
uk.y = some_value;
如果成员不是平凡的(例如std::string
),那么您必须首先销毁当前活动的成员,然后使用 placement-new 初始化另一个成员:
uk.x.~X();
::new (&uk.y) Y /*parenthesised or braced init arguments here*/;
请注意,如果联合包含非平凡成员,则其所有特殊成员函数(默认构造函数除外)从析构函数到复制构造函数再到赋值运算符都将被隐式删除。因此,您需要为类似联合的 class 包装它定义那些。每个人都必须知道当前活跃的成员,并据此采取行动。
另请注意,析构函数不会隐式销毁联合成员,这与正常 class 不同,后者会在析构函数主体之后销毁成员。这必须像我上面显示的那样明确地完成。
P.S。标准库中有一个标准的标记联合:std::variant
。无需自己发明。