考虑以下最小工作示例:
#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
?
答案 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支持编译就无法编译。