问题
Consider the following minimal working example:
#include <atomic>
int main() {
::std::atomic<bool> a = false;
}
Copy ctor and copy assignment of atomic are both explicitly deleted. However, this should invoke the ctor taking exactly a bool.
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;
^ ~~~~~
Why are they trying to copy an atomic
?
回答1:
It tries to invoke the copy constructor because its move constructor has been implicitly deleted.
Suppose we have a class X.
struct X
{
X(const X&) = delete; // user-declared
X(int)
{
}
};
Now, if you were to write
X x = 4;
it would be the same as
X x = X(4); // copy/move into x, see 15.6.1
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 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 ]
In C++17 this changes with the introduction of guaranteed copy elision.
This results in the line being equal to
X x(4);
which does not rely on either copy or move constructor and instead calls X(int)
.
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.
来源:https://stackoverflow.com/questions/48883194/why-does-the-initialisation-of-an-object-invoke-the-copy-constructor