C++ 分配给已删除/未初始化的对象
我有一节这样的课C++ 分配给已删除/未初始化的对象,c++,c++11,initialization,destructor,unions,C++,C++11,Initialization,Destructor,Unions,我有一节这样的课 struct foo { bool type; union { struct { std::string s; }; struct { std::function<std::string(void)> f; }; }; }; structfoo{ 布尔型; 联合{ 结构{std::string s;}; 结构{std::function f;}; }; }; 我需要定义赋值运算符,但当我赋值不同的类型时,我
struct foo {
bool type;
union {
struct { std::string s; };
struct { std::function<std::string(void)> f; };
};
};
structfoo{
布尔型;
联合{
结构{std::string s;};
结构{std::function f;};
};
};
我需要定义赋值运算符,但当我赋值不同的类型时,我基本上是赋值给未初始化的字段(我知道我必须先显式调用析构函数)
我猜这样的赋值是未定义的行为,因为我不知道字符串或函数的赋值是否不重用某些字段
如何在不调用任何未定义行为的情况下正确执行此操作
我仅限于C++ 11。< /P> < P>第一,C++中的匿名结构不好。例如,您可以使用:
union {
std::string s;
std::function<std::string(void)> f;
};
联合{
std::字符串s;
std::函数f;
};
我的猜测是,这种分配是未定义的行为
对
如何在不调用任何未定义行为的情况下正确执行此操作
可以使用标记的联合模式。您似乎已经有了类型
成员。您可以使用它来指定哪个成员处于活动状态。如果您对该成员有其他计划,只需添加一个新计划即可
一旦可以使用结构成员检查哪个联合成员处于活动状态,就可以销毁活动成员,然后复制并构造以前的非活动联合成员,最后更新type
以表示新的活动成员
也就是说,您可以通过使用标记的联合的预先存在的通用实现来节省一些时间。其中有一个例子,
首先,C++中的匿名结构不好。例如,您可以使用:
union {
std::string s;
std::function<std::string(void)> f;
};
联合{
std::字符串s;
std::函数f;
};
我的猜测是,这种分配是未定义的行为
对
如何在不调用任何未定义行为的情况下正确执行此操作
可以使用标记的联合模式。您似乎已经有了类型
成员。您可以使用它来指定哪个成员处于活动状态。如果您对该成员有其他计划,只需添加一个新计划即可
一旦可以使用结构成员检查哪个联合成员处于活动状态,就可以销毁活动成员,然后复制并构造以前的非活动联合成员,最后更新type
以表示新的活动成员
也就是说,您可以通过使用标记的联合的预先存在的通用实现来节省一些时间。举个例子,有一个 我猜这样的赋值是未定义的行为,因为我不知道字符串或函数的赋值是否不重用某些字段 猜对了!赋值的前提条件始终是左侧实际上是该类型的对象。如果左手边没有物体,所有的赌注都没有了 如何在不调用任何未定义行为的情况下正确执行此操作 建筑!当您没有对象时,获取对象的唯一方法是创建它。因为我们想在一个特定的位置创建它,这是新的 我不知道为什么要将类型包装在一个额外的结构中,您想这样做:
union U {
U() { }
~U() { }
std::string s;
std::function<std::string(void)> f;
} u;
union U{
U(){}
~U(){}
std::字符串s;
std::函数f;
}u;
这样,您的赋值运算符将是:
foo& operator=(foo const& rhs) {
if (type) {
if (rhs.type) {
u.s = rhs.u.s;
} else {
u.s.~string();
new (&u.f) std::function<std::string(void)>(rhs.u.f);
}
} else {
if (!rhs.type) {
u.f = rhs.u.f;
} else {
u.f.~function();
new (&u.s) std::string(rhs.u.s);
}
}
return *this;
}
foo&operator=(foo const&rhs){
如果(类型){
if(rhs类型){
u、 s=rhs.u.s;
}否则{
u、 s.~string();
新(&u.f)标准::功能(rhs.u.f);
}
}否则{
如果(!rhs.type){
u、 f=右S.u.f;
}否则{
u、 f.~函数();
新(&u.s)标准::字符串(rhs.u.s);
}
}
归还*这个;
}
您可能希望重构其中的一些,以支持移动分配,而不需要大量重复,但这只是一个粗略的想法
我猜这样的赋值是未定义的行为,因为我不知道字符串或函数的赋值是否不重用某些字段
猜对了!赋值的前提条件始终是左侧实际上是该类型的对象。如果左手边没有物体,所有的赌注都没有了
如何在不调用任何未定义行为的情况下正确执行此操作
建筑!当您没有对象时,获取对象的唯一方法是创建它。因为我们想在一个特定的位置创建它,这是新的
我不知道为什么要将类型包装在一个额外的结构中,您想这样做:
union U {
U() { }
~U() { }
std::string s;
std::function<std::string(void)> f;
} u;
union U{
U(){}
~U(){}
std::字符串s;
std::函数f;
}u;
这样,您的赋值运算符将是:
foo& operator=(foo const& rhs) {
if (type) {
if (rhs.type) {
u.s = rhs.u.s;
} else {
u.s.~string();
new (&u.f) std::function<std::string(void)>(rhs.u.f);
}
} else {
if (!rhs.type) {
u.f = rhs.u.f;
} else {
u.f.~function();
new (&u.s) std::string(rhs.u.s);
}
}
return *this;
}
foo&operator=(foo const&rhs){
如果(类型){
if(rhs类型){
u、 s=rhs.u.s;
}否则{
u、 s.~string();
新(&u.f)标准::功能(rhs.u.f);
}
}否则{
如果(!rhs.type){
u、 f=右S.u.f;
}否则{
u、 f.~函数();
新(&u.s)标准::字符串(rhs.u.s);
}
}
归还*这个;
}
您可能希望重构其中的一些,以支持移动分配,而不需要大量重复,但这只是一个粗略的想法 C++11非常友好,甚至不允许这样做。由于联合包含具有非平凡构造函数和析构函数的字段,
struct foo
已隐式删除默认构造函数和析构函数
我的老版本3.4.1(带有选项std=c++11)在尝试创建struct foo
时阻塞了:
error: call to implicitly-deleted
及
如果我尝试手动初始化struct foo
(我稍微更改了foo
,以避免匿名字段):
及
C++11非常友好,甚至不允许这样做。由于联合包含具有非平凡构造函数和析构函数的字段,
struct foo
已隐式删除默认构造函数和析构函数
我的老版本3.4.1(带有选项std=c++11)在我尝试运行时阻塞了
note: destructor of 'foo' is implicitly deleted because variant field 's' has a non-trivial destructor
struct { std::string s; } s;
^