为啥工会成员数据没有默认初始化?
Posted
技术标签:
【中文标题】为啥工会成员数据没有默认初始化?【英文标题】:Why aren't union member data default-initialized?为什么工会成员数据没有默认初始化? 【发布时间】:2021-08-19 23:50:07 【问题描述】:AFAIK 一个类/结构/联合,它不会在构造函数初始化器列表中初始化其成员数据,然后它们被默认初始化。如果成员数据是内置整数类型,则它具有不确定的值。如果它是类类型,则调用其 default-ctor(需要可访问且不可删除的 default-ctor)。
这是我的例子:
struct A
A()std::cout << "A()\n";
A(int)std::cout << "A(int)\n";
A(A const&)std::cout << "A(A const&)\n";
~A()std::cout << "~A()\n";
A& operator = (A const& )std::cout << "=(Aconst&)\n"; return *this;
;
struct B
B(int)std::cout << "B(int)\n"; // a_ and d_ are default-init
double d_;
A a_;
;
B b = 10;
输出:
A()
B(int)
~A()
没关系,因此构造函数B(int)
不会显式初始化其ctor-init 列表中的成员d_
和a_
,因此它们是默认初始化。 d_
有一个未定义的值。而a_
是默认初始化。
直到这里我都还好,但是 union
的成员呢:
union U
U()std::cout << "U()\n"; // needed because a_'s class type has defined a user-defined version
U(U const&)std::cout << "U(U const&)\n"; // needed as above
~U()std::cout << "~U()\n"; // needed as above
A a_; // has defined copy-control members
int i_;
;
U u1;
U u2 = u1;
输出:
U()
U(U const&)
~U()
~U()
如您所见:union U
没有在其 ctor-init-list 中初始化其成员数据 a_
和 i_
,这些成员也没有在类内初始化,但没有调用它们的构造函数!所以:
union
的成员数据是否在构造函数初始化列表中被默认初始化?谢谢!
【问题讨论】:
您希望union
准确调用哪个成员构造函数?如果多个联合成员属于定义了构造函数的类型怎么办?它不能多次初始化同一个内存。在将值实际分配给union
之前,它甚至不知道哪个成员处于活动状态。事实上,在 C++11 之前,联合甚至不能容纳定义了构造函数的成员。在现代 C++ 中处理同一内存中的多种类型的正确方法是尽可能使用std::variant
而不是union
。
工会一次只有一个有效成员。您如何期望 C++ 选择初始化哪个?如果它们都是类类型,那么对它们进行初始化将是一个主要问题,因为第二次初始化会随机地覆盖之前由第一次初始化写入的内存。
您希望 C++ 如何选择初始化哪个? 当然是心灵感应。我们应该用 C++8191 解决这个问题。
【参考方案1】:
如你所见:联合U没有初始化它的成员数据a_和i_
联合只有一个成员处于活动状态,因此永远不会出现可以初始化两个成员的情况。
如果您不在用户定义的构造函数中提供初始化程序,则不会初始化联合的成员。
【讨论】:
【参考方案2】:联合只是一个位置的多个名称(引用) 无论您修改哪个成员,都只会处理一个位置 因此所有其他成员都将被修改
union _Union
int i; // 4 bytes.
long ll; // 4 bytes.
float f; // 4 bytes.
char*txt; // 4 bytes.
;
sizeof(_Union) = 4 bytes
如果结构体大小为 16 字节
联合的大小是最大成员的大小
如果上面的_Union
有另一个long long int
成员,那么它的大小将是 8 个字节
因为long long int
是 8
【讨论】:
停止使用以下划线开头的标识符,它们可能与核心语言的标识符发生冲突。以上是关于为啥工会成员数据没有默认初始化?的主要内容,如果未能解决你的问题,请参考以下文章