为什么对象的初始化调用复制构造函数? [英] Why does the initialisation of an object invoke the copy constructor?
问题描述
考虑以下最小工作示例:
Consider the following minimal working example:
#include <atomic>
int main() {
::std::atomic<bool> a = false;
}
原子的复制ctor和复制分配均被明确删除.但是,这应调用 ctor并采取精确的布尔值.
Copy ctor and copy assignment of atomic are both explicitly deleted. However, this should invoke the ctor taking exactly a bool.
g ++和clang ++都抱怨这行试图调用 atomic
的副本ctor:
Both g++ and clang++ complain that this line is attempting to invoke the copy ctor of 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
?
推荐答案
它尝试调用副本构造函数,因为其move构造函数已被隐式删除.
It tries to invoke the copy constructor because its move constructor has been implicitly deleted.
假设我们有一个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
,你会得到的编译错误一>,因为您显式删除了复制构造函数,因此没有隐式声明任何move构造函数.
and you would get a compilation error because you explicitly deleted the copy constructor and therefore no move constructor is being implicitly declared.
15.8.1复制/移动构造函数
[...]
如果类X的定义未明确声明移动构造函数,则仅当且仅当非显式类的隐式声明为默认值
If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
- X没有用户声明的副本构造函数,
- X没有用户声明的副本分配运算符,
- X没有用户声明的移动分配运算符,并且
- X没有用户声明的析构函数.
[注意:当未隐式声明move构造函数或明确提供的表达式,否则将调用move构造函数可以代替调用副本构造函数.— 尾注]
[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. — end note ]
在C ++ 17中,这种情况随着引入保证的复制省略.
这导致该行等于
In C++17 this changes with the introduction of guaranteed copy elision.
This results in the line being equal to
X x(4);
不依赖于复制或移动构造函数,而是调用 X(int)
.
which does not rely on either copy or move constructor and instead calls X(int)
.
像 X , std::atomic 也将其副本构造函数明确删除这就是为什么如果不使用C ++ 17支持进行编译,则代码将无法编译的原因.
Like X, std::atomic also has its copy constructor explicitly deleted which is why your code fails to compile if not compiled with C++17 support.
这篇关于为什么对象的初始化调用复制构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!