为什么对象的初始化会调用复制构造函数?

时间:2018-02-20 10:33:37

标签: c++ initialization atomic copy-constructor

考虑以下最小工作示例:

#include <atomic>

int main() {
  ::std::atomic<bool> a = false;
}

复制ctor和原子的复制分配都被明确删除。但是,这应该调用ctor taking exactly a bool

g ++和clang ++都抱怨此行试图调用atomic的副本:

$ g++ -std=c++1z a.cpp 
a.cpp: In function ‘int main()’:
a.cpp:4:27: error: use of deleted function ‘std::atomic<bool>::atomic(const std::atomic<bool>&)’
   ::std::atomic<bool> a = false;
                           ^~~~~
$ clang++ -std=c++1z a.cpp 
a.cpp:4:23: error: copying variable of type '::std::atomic<bool>' invokes deleted constructor
  ::std::atomic<bool> a = false;
                      ^   ~~~~~

他们为什么要复制atomic

1 个答案:

答案 0 :(得分:1)

它尝试调用复制构造函数,因为它的移动构造函数已被隐式删除。

假设我们有一个X类。

struct X
{
    X(const X&) = delete; // user-declared

    X(int)
    {
    }
};

现在,如果你要写

X x = 4;

它与

相同
X x = X(4); // copy/move into x, see 15.6.1

并且你会得到compilation error,因为你明确删除了复制构造函数,因此没有隐式声明移动构造函数。

  

15.8.1复制/移动构造函数

     

[...]

     

如果类X的定义没有显式地声明移动构造函数,则当且仅当

时,非显式构造函数将被隐式声明为默认值。      
      
  • X没有用户声明的复制构造函数,
  •   
  • X没有用户声明的复制赋值运算符
  •   
  • X没有用户声明的移动赋值运算符和
  •   
  • X没有用户声明的析构函数。
  •   
     

[注意:未隐式声明移动构造函数或   显式提供,否则将调用的表达式   移动构造函数可能会调用复制构造函数。 - 结束记录]

在C ++ 17中,随着保证copy elision的引入,这会发生变化 这导致该行等于

X x(4);

不依赖于复制或移动构造函数而是调用X(int)

X 一样, std::atomic 也明确删除了其复制构造函数 这就是为什么你的代码如果没有用C ++ 17支持编译就无法编译。