数组成员初始化用户定义的类型

mir*_*irk 6 c++ constructor c++11

g ++ 4.7支持数组成员初始化,我开始玩它.

下面的代码无法编译.

struct A
{
   A(int){};
   A(const A&) = delete;
   A& operator=(const A&) = delete;
   ~A(){};
};

struct B
{
   B():
      a{{0},{1}}
   {};
   A a[2];
};

B b;
Run Code Online (Sandbox Code Playgroud)

gcc 4.8(预发布)的错误消息是:

n.cc: In constructor ‘B::B()’:
n.cc:12:20: error: use of deleted function ‘A::A(const A&)’
           a{{0},{1}}
             ^
n.cc:4:8: error: declared here
        A(const A&) = delete;
        ^
Run Code Online (Sandbox Code Playgroud)

有没有办法让这段代码有效?我不能轻易地改变A的构造函数,析构函数.我似乎需要一个move-constructor或copy-constructor来初始化数组,但这似乎是违反直觉的,因为我真正想要的就是就地构造.

如果我在2个成员a0和a1中分割[2]并分别构造它们,它就可以工作.然而,这看起来很可疑.

ild*_*arn 2

数组是聚合,聚合初始化始终使用复制初始化。C++11\xc2\xa78.5.1/1:

\n\n
\n

聚合是一个数组类,没有用户提供的构造函数,没有非静态数据成员的大括号或等于初始化器,没有私有或受保护的非静态数据成员,没有基类,也没有虚函数。

\n
\n\n

\xc2\xa78.5.1/2:

\n\n
\n

当聚合由初始值设定项列表初始化时,如 8.5.4 中所指定,初始值设定项列表的元素将被视为聚合成员的初始值设定项,按递增的下标或成员顺序。每个成员都是从相应的初始化子句复制初始化的。……

\n
\n\n

(强调我的。)

\n\n

此外,如果存在用户声明的复制构造函数 (\xc2\xa712.8/9),则编译器不会隐式生成移动构造函数;因为您有一个用户声明的复制构造函数,该构造函数被定义为已删除,所以A既没有复制也没有移动构造函数。显式添加移动构造函数是有效的:

\n\n
struct A\n{\n   A(int) { }\n   A(A const&) = delete;\n   A& operator = (A const&) = delete;\n   A(A&&) = default;\n   ~A() = default;\n};\n\nstruct B\n{\n   B() : a{{0}, {1}} { }\n   A a[2];\n};\n\nint main()\n{\n   B b;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在线演示

\n\n

这与您想要得到的差不多。

\n