C ++成员初始化和构造函数

时间:2014-11-13 23:05:24

标签: c++

如果没有定义构造函数,我可以使用成员初始化:

struct B {
  A a_;
};

以后可以说

B b {A()};

这是有效的,因为不涉及A的复制或移动。但是,只要我为B定义移动构造函数,上面的代码就不再编译。如何同时进行成员初始化和某些构造函数共存?

2 个答案:

答案 0 :(得分:3)

如果B是聚合类型,则A是一种聚合类型。

B b {A()};

是聚合初始化。

将移动构造函数添加到B时,B将停止为聚合类型。因此,您无法使用聚合初始化来初始化B的实例。

从标准(强调我的):

  

8.5.1聚合 [dcl.init.aggr]

     

1 聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有 brace-or-equalinitializers < / em>对于非静态数据成员(9.2),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3)

答案 1 :(得分:1)

R Sahu给出的答案已经是正确的了,但是我想补充说,添加一个构造函数没有效率损失,这个构造函数执行了成员初始化所做的事情:

struct B {
  A a_;
  B(const A& a) : a_(a) {}
}

现在调用B b {A()};与使用聚合初始化时的效率完全相同。

更新: 看完评论后,我测试了我的断言:

struct Foo
{
        Foo() { std::cout << "Foo default" << std::endl; }
        Foo(const Foo& other) { std::cout << "Foo copy" << std::endl; }
};

struct Bar
{
        Foo f;
        // #1 Bar(const Foo& f) : f(f) {}
};

int main()
{
        Bar b { Foo() };
}

如上所示,此应用程序仅输出

Foo default

如果我取消注释#1,我就会

Foo default
Foo copy

正如原始海报所示(GCC 4.9与-O3)。我必须更多地使用非打印构造函数来查看这是否总是正确或者只是在有副作用时,但我想更新这篇文章以澄清它不像我建议的那样干燥和干燥。