如何在联合中初始化非 POD 成员

How to initialize a non-POD member in Union

本文关键字:初始化 POD 成员      更新时间:2023-10-16

在 c++11 中,Union 支持非 POD 成员。我想在构造函数中初始化一个非 POD 成员。

在维基百科 c++11 页面上,它使用放置"new"来初始化非 POD 成员。

#include <new> // Required for placement 'new'.
struct Point {
    Point() {}
    Point(int x, int y): x_(x), y_(y) {}
    int x_, y_;
};
union U {
    int z;
    double w;
    Point p; // Illegal in C++03; legal in C++11.
    U() {new(&p) Point();} // Due to the Point member, a constructor definition is now required.
};

我想知道如果我使用 ctor-initializer-list 而不是放置"new"有什么区别?

U() : p() {}

不,对你来说没有区别。只需使用U() : p() {}.

[ 注意:通常,必须使用显式析构函数调用和放置新运算符来更改活动 工会成员。— 尾注 ]

[ 示例:假设联合类型 U 的对象 u 具有非静态数据 成员m类型为 Mn类型为 N。如果M有一个非平凡析构函数,N有一个非平凡构造函数 (例如,如果它们声明或继承虚函数(,可以使用析构函数和放置新运算符安全地将 u 的活动成员从 m 切换到 n,如下所示:

u.m.~M();
new (&u.n) N;

— 结束示例 ]

即您的第一个变体是正确的。


该标准还说:

联合中最多一个非静态数据成员可以具有大括号或等于初始值设定项。

就个人而言,我希望以下内容是正确的:

union U {
    int z;
    double w;
    Point p {1,2};
};
#include <iostream>
int main () {
    U u;
    std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
}

我希望输出1:2,但是使用 g++ 4.8.1 我得到垃圾值。当我尝试时

union U {
    int z;
    double w;
    Point p = Point(1,2);
};

我也得到垃圾值。我不确定这是否是编译器错误。

编辑:联合中的大括号或等于初始值设定项

您最多可以在 ctor-initializer-list 中初始化一个联合成员。联合是一个类,因此 [class.base.init] (C++11 §12.6.2( 中成员初始值设定项的规则就像它们适用于具有类键structclass的类一样。12.6.2/8 中指出了一个明显的例外:"尝试初始化联合的多个非静态数据成员会使程序格式不正确。