为什么对象的初始化会调用复制构造函数?
Why does the initialisation of an object invoke the copy constructor?
考虑以下最小工作示例:
#include <atomic>
int main() {
::std::atomic<bool> a = false;
}
atomic 的复制构造函数和复制赋值都被显式删除。但是,这应该调用 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
?
它试图调用复制构造函数,因为它的移动构造函数已被隐式删除。
假设我们有一个 class 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 Copy/move constructors
[...]
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 does not have a user-declared copy constructor,
- X does not have a user-declared copy assignment operator,
- X does not have a user-declared move assignment operator, and
- X does not have a user-declared destructor.
[ 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 中,随着保证 copy elision.
的引入,这种情况发生了变化
这导致该行等于
X x(4);
它不依赖于复制或移动构造函数而是调用 X(int)
.
和X一样,std::atomic也明确删除了它的复制构造函数
这就是为什么如果不使用 C++17 支持编译代码将无法编译的原因。
考虑以下最小工作示例:
#include <atomic>
int main() {
::std::atomic<bool> a = false;
}
atomic 的复制构造函数和复制赋值都被显式删除。但是,这应该调用 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
?
它试图调用复制构造函数,因为它的移动构造函数已被隐式删除。
假设我们有一个 class 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 Copy/move constructors
[...]
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 does not have a user-declared copy constructor,
- X does not have a user-declared copy assignment operator,
- X does not have a user-declared move assignment operator, and
- X does not have a user-declared destructor.
[ 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 中,随着保证 copy elision.
的引入,这种情况发生了变化
这导致该行等于
X x(4);
它不依赖于复制或移动构造函数而是调用 X(int)
.
和X一样,std::atomic也明确删除了它的复制构造函数 这就是为什么如果不使用 C++17 支持编译代码将无法编译的原因。