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;
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;
^
有没有办法让这段代码有效?我不能轻易改变A的构造函数,析构函数。 我似乎需要一个move-constructor或copy-constructor来初始化数组,但这似乎是违反直觉的,因为我真正想要的只是就地构造。
如果我在2个成员a0和a1中拆分[2]并分别构造它们,它就有效。然而,这看起来很可疑。
答案 0 :(得分:4)
在聚合(8.5.1)的 list-initialization (8.5.4p1)中,对聚合元素执行的初始化形式是copy-initialization(8.5.1p2),甚至如果初始化是 direct-list-initialization :
当初始化列表初始化聚合时,如8.5.4中所指定的,初始化列表的元素被视为聚合成员的初始化者,增加下标或成员顺序。每个成员都是从相应的 initializer-clause 中复制初始化的。
然而,仅仅因为执行初始化的形式是复制初始化并不意味着发生了复制。根据{{3}}, copy-list-initialization 应该与 direct-list-initialization 相同,但不允许使用显式构造函数。
答案 1 :(得分:2)
数组是聚合,聚合初始化总是使用复制初始化。 C ++11§8.5.1/ 1:
聚合是一个数组或没有用户提供的构造函数的类,没有用于非的大括号或等于初始化程序 -static数据成员,没有私有或受保护的非静态数据成员,没有基类,也没有虚函数。
第8.5.1节/ 2:
当初始化程序列表初始化聚合时,如8.5.4中所述,初始化程序列表的元素将作为聚合成员的初始化程序,增加下标或成员顺序。 每个成员都是从相应的初始化子句中复制初始化的。 ...
(强调我的。)
此外,如果存在用户声明的复制构造函数,则编译器不会隐式生成移动构造函数(§12.8/ 9);因为您有一个被定义为已删除的用户声明的复制构造函数,A
既没有复制也没有移动构造函数。显式添加移动构造函数:
struct A
{
A(int) { }
A(A const&) = delete;
A& operator = (A const&) = delete;
A(A&&) = default;
~A() = default;
};
struct B
{
B() : a{{0}, {1}} { }
A a[2];
};
int main()
{
B b;
}
<子> Online demo 子>
这与你想要的一样接近。