工会成员分配中的C++分段错误



以下代码在分配给union成员时产生分段错误。这一定是工会误解的结果,但我不能指出我的错误。

Q1:是否有必要在T1的构造函数中为适当的并集成员变量进行一些初始化

我尝试了类似于建议的解决方案(在下面的代码块中找到(的方法来初始化适当的成员,但没有成功。

Q2:如果T1初始化正常,为什么分配到此位置会产生分段故障

相关代码:

struct T1
{
T1(int type)
{
this->type = type;
//Q1 : need to init appropriate union struct here also? Something like:
/*
*if (type == 1)  
*{
*    union_member1.str = "";
*}
*else
*{
*    union_member2.value = 0;
*}
*/
//If so, better alternative to this?
}
int type;           //tells which union struct is used

union               
{
struct              //type 1
{
std::string str;
} union_member1;
struct              //type 2
{
int value;
} union_member2;
};
};
struct T2
{
bool used;
/*
* other variables here
*/
}; 
std::map<std::string, T2> mymap;
T1* global_ptr;
int main()
{
for (auto& map_entry : mymap)
{
if (!(map_entry.second.used))
{
global_ptr = new T1(1);                                 
global_ptr->union_member1.str = map_entry.first;        //Q2: SEG fault occurs with this assignment
std::string s = map_entry.first;                        //    but not with this assignment
}
}
}

GDB输出

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b70b03 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6

显然,出于可读性的原因,对这些代码进行了精简。地图条目也经过了彻底验证。

https://eel.is/c++草案/类工会#general-6

表示只有当赋值是一个琐碎的赋值运算符时,才能通过u.x = ...更改并集的活动成员。std::string赋值运算符不是平凡的,因此注释应用

https://eel.is/c++草案/类工会#general-7

如果上述规则不适用,则只能通过使用placement new表达式来更改并集的活动成员。

如果字符串直接是联合成员,您将执行

if (type == 1)  
{
new (&union_member_str) std::string();
}

但它是一个未命名的struct类型的联合成员的子对象,因此您可以使用placement new来构造整个struct,并负责其所有子对象:

if (type == 1)  
{
using UMT = decltype(union_member1);
// or
// typedef decltype(union_member1) UMT;
new (&union_member1) UMT();
}

当然,您还需要对复制构造函数、移动构造函数、复制赋值、移动赋值和析构函数进行适当的处理(第5条规则(。因此,使用现有的类(如std::variant(要好得多。

直接字符串成员对应的析构函数片段是

if (type == 1)  
{
union_member_str.string::~string();
}

对于您未命名的struct

if (type == 1)  
{
using UMT = decltype(union_member1);
union_member1.UMT::~UMT();
}

甚至不要试图在没有typedef/type别名的情况下编写这些。

相关内容

  • 没有找到相关文章

最新更新