C++非静态数据成员初始化器,只是有点困惑

Fer*_*eak 13 c++ c++11

我对以下代码执行的操作有点困惑:

class Base
{
public:
    Base() = default;
    Base(const Base &) =delete;
    Base &operator=(const Base &) = delete;
    Base(const char*) {}
};

class Holder
{
public:
    Holder() = default;
private:
    // Base b = Base();
    Base b2 = {};
};

int main()
{
    Holder h;
}
Run Code Online (Sandbox Code Playgroud)

在这个版本中,它编译,但是如果我取消注释Base b = Base();它会给出以下错误:

main.cpp:15:17: error: use of deleted function 'Base::Base(const Base&)'
   Base b = Base();
                 ^
main.cpp:5:6: note: declared here
      Base(const Base &) =delete;
      ^
Run Code Online (Sandbox Code Playgroud)

我只是无法在标准中找到为什么它试图为Base b = Base()初始化程序调用复制构造函数,为什么它不需要Base b2 = {}...或者这只是隐藏在几个单词中的那些小晦涩之一在一个段落?

你能否(短)解释为什么会这样?

(coliru:http://coliru.stacked-crooked.com/a/c02ba0293eab2ce5 )

Yam*_*vic 8

这是因为,从概念上讲,该构造来自Base(),需要复制/移动构造函数.你没有意识到这一点的可能原因是因为该表达式通常会触发复制省略:标准优化.这是C++陷阱之一.

(31.3) - 当一个未绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv-nonqualified类型的类对象时,可以通过构造临时对象来省略复制/移动操作直接进入省略复制/移动的目标.

至于为何Base b2 = {}有效,请参阅

(3.4) - 否则,如果初始化列表没有元素而T是具有默认构造函数的类类型,则对象是值初始化的.

你可以做到Base b;.


eer*_*ika 5

T object = {arg1, arg2, ...};列表初始化的语法.没有涉及复制.

T object = T()不是列表初始化.右手操作数构造一个值初始化的临时值,并object从中进行移动或复制初始化.移动和复制可以省略,但类型必须是可移动的或可复制的,否则这是不允许的.

  • `Base`不是聚合,因为它有一个用户提供的构造函数`Base(const char*)`. (2认同)
  • 是的,更确切地说是*"copy-list-initialization"*,在这种情况下,值初始化`Base`,即调用其默认构造函数. (2认同)