Why does the initialisation of an object invoke the copy constructor?

梦想与她 提交于 2021-02-16 16:10:40

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!