为啥工会成员数据没有默认初始化?

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

【讨论】:

停止使用以下划线开头的标识符,它们可能与核心语言的标识符发生冲突。

以上是关于为啥工会成员数据没有默认初始化?的主要内容,如果未能解决你的问题,请参考以下文章

java成员变量怎么默认初始化

为啥类的常量数据成员需要在构造函数中初始化?

为啥不能在派生类的构造函数初始化列表中初始化基类的数据成员?

分类为啥不能添加成员变量

没有默认构造函数的成员对象的初始化列表

成员初始化器列表和非静态数据成员的默认成员初始化器有啥区别?