【问题标题】: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 解决这个问题。

标签: c++ class initialization union


【解决方案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

    【讨论】:

    • 停止使用以下划线开头的标识符,它们可能与核心语言的标识符发生冲突。
    猜你喜欢
    • 2021-06-13
    • 1970-01-01
    • 2013-10-14
    • 2016-04-15
    • 2016-04-26
    • 2019-09-10
    • 2015-10-07
    • 2012-08-29
    • 1970-01-01
    相关资源
    最近更新 更多