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

bit*_*ask 8 c++ initialization atomic copy-constructor

考虑以下最小的工作示例:

#include <atomic>

int main() {
  ::std::atomic<bool> a = false;
}
Run Code Online (Sandbox Code Playgroud)

复制ctor和原子的复制分配都被明确删除.但是,这应该调用ctor完全是一个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;
                      ^   ~~~~~
Run Code Online (Sandbox Code Playgroud)

他们为什么要复制atomic

Axa*_*alo 1

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

\n\n

假设我们有一个 X 类。

\n\n
struct X\n{\n    X(const X&) = delete; // user-declared\n\n    X(int)\n    {\n    }\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,如果你要写

\n\n
X x = 4;\n
Run Code Online (Sandbox Code Playgroud)\n\n

它会是一样的

\n\n
X x = X(4); // copy/move into x, see 15.6.1\n
Run Code Online (Sandbox Code Playgroud)\n\n

并且您会收到编译错误,因为您显式删除了复制构造函数,因此没有隐式声明移动构造函数。

\n\n
\n

15.8.1 复制/移动构造函数

\n\n

[...]

\n\n

如果类 X 的定义没有显式声明移动构造函数,则非显式移动构造函数将被隐式声明为默认当且仅当

\n\n
    \n
  • X 没有用户声明的复制构造函数,
  • \n
  • X 没有用户声明的复制赋值运算符,
  • \n
  • X 没有用户声明的移动赋值运算符,并且
  • \n
  • X 没有用户声明的析构函数。
  • \n
\n\n

[注意:当未隐式声明或显式提供移动构造函数时,本来会调用移动构造函数的表达式可能会调用复制构造函数。\xe2\x80\x94尾注]

\n
\n\n

在 C++17 中,这种情况随着保证复制省略的引入而改变。
\n这导致该行等于

\n\n
X x(4);\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

与X一样,std::atomic也显式删除了其复制构造函数\n这就是为什么如果未使用 C++17 支持进行编译,您的代码将无法编译。

\n