具有重要成员的 C++11 匿名 union

标签 c++ constructor c++11 anonymous unions

我正在更新我的一个结构,我想向它添加一个 std::string 成员。原始结构如下所示:

struct Value {
  uint64_t lastUpdated;

  union {
    uint64_t ui;
    int64_t i;
    float f;
    bool b;
  };
};

仅仅向 union 中添加一个 std::string 成员当然会导致编译错误,因为通常需要添加对象的非平凡构造函数。 In the case of std::string (text from informit.com)

Since std::string defines all of the six special member functions, U will have an implicitly deleted default constructor, copy constructor, copy assignment operator, move constructor, move assignment operator and destructor. Effectively, this means that you can't create instances of U unless you define some, or all of the special member functions explicitly.

然后网站继续给出如下示例代码:

union U
{
int a;
int b;
string s;
U();
~U();
};

但是,我在结构中使用匿名 union 。我在 freenode 上询问了##C++,他们告诉我正确的方法是将构造函数放在结构中,并给了我这个示例代码:

#include <new>

struct Point  {
    Point() {}
    Point(int x, int y): x_(x), y_(y) {}
    int x_, y_;
};

struct Foo
{
  Foo() { new(&p) Point(); }
  union {
    int z;
    double w;
    Point p;
  };
};

int main(void)
{
}

但是从那里我不知道如何定义 std::string 需要定义的其余特殊函数,此外,我并不完全清楚该示例中的 ctor 是如何工作的。

我可以请人向我解释清楚一点吗?

最佳答案

这里不需要放置新的。

变量成员不会被编译器生成的构造函数初始化,但是选择一个并使用普通的ctor-initializer-list初始化它应该没有问题。在匿名 union 中声明的成员实际上是包含类的成员,并且可以在包含类的构造函数中初始化。

此行为在第 9.5 节中描述。 [class.union]:

A union-like class is a union or a class that has an anonymous union as a direct member. A union-like class X has a set of variant members. If X is a union its variant members are the non-static data members; otherwise, its variant members are the non-static data members of all anonymous unions that are members of X.

在第 12.6.2 节 [class.base.init]:

A ctor-initializer may initialize a variant member of the constructor’s class. If a ctor-initializer specifies more than one mem-initializer for the same member or for the same base class, the ctor-initializer is ill-formed.

所以代码可以很简单:

#include <new>

struct Point  {
    Point() {}
    Point(int x, int y): x_(x), y_(y) {}
    int x_, y_;
};

struct Foo
{
  Foo() : p() {} // usual everyday initialization in the ctor-initializer
  union {
    int z;
    double w;
    Point p;
  };
};

int main(void)
{
}

当然,当激活一个变量成员而不是在构造函数中初始化的另一个成员时,仍然应该使用placement new。

关于具有重要成员的 C++11 匿名 union ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10693913/

相关文章:

c++ - 使用 boost::serialization 序列化 TAO/CORBA 对象

javascript - 在 React 中使用类的目的是什么?

c++ - 访问基类的私有(private)变量时派生类出错

c++ - 指向函数签名中 const 的智能指针

c++ - 类模板中文字运算符的Friend声明

c++ - 不匹配运算符<<

文件的 C++ OpenSSL 哈希值不正确

c++ - 在天穹上使用点光源的奇怪照明效果

c++ - Borland C++ 5.02 无法调用带参数的构造函数

javascript - 如何从父对象构造函数访问对象