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

新手上路,请多包涵

我对为什么下面的代码做了它的作用有点困惑:

 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;
}

在这个化身中,它可以编译,但是如果我取消注释 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;
      ^

而且我只是无法在标准中找到为什么它尝试为 Base b = Base() 初始化程序调用复制构造函数,为什么它不调用 Base b2 = {} ……或者是这只是隐藏在某段某处的几句话中的那些小晦涩之一?

您能否给出一个(简短的)解释为什么会发生这种情况?

(大肠杆菌: http ://coliru.stacked-crooked.com/a/c02ba0293eab2ce5)

原文由 Ferenc Deak 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 291
1 个回答

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

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

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

(3.4) — 否则,如果初始值设定项列表没有元素并且 T 是具有默认构造函数的类类型,则该对象是值初始化的。

你可以做 Base b;

原文由 Yam Marcovic 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题