In C++98, the C++ compiler could automatically generate copy constructor and copy assignment operator via member-wise copy, e.g.
struct X { std::string s; std::vector<int> v; int n; };
The compiler automatically generates copy constructor and copy assignment operator for X
, using member-wise copy.
But how do things change in C++11 with move semantics?
Are the move constructor and move assignment operator automatically generated, like copy constructors and copy assignment operators?
Are there cases in which move operations are not automatically generated?
If a copy constructor, copy-assignment operator, move constructor, move-assignment operator, or destructor is explicitly declared, then: No move constructor is automatically generated. No move-assignment operator is automatically generated.
A copy assignment operator of class T is a non-template non-static member function with the name operator= that takes exactly one parameter of type T, T&, const T&, volatile T&, or const volatile T&. For a type to be CopyAssignable, it must have a public copy assignment operator.
The copy constructor is a constructor which creates an object by initializing it with an object of the same class, which has been created previously. The copy constructor is used to − Initialize one object from another of the same type. Copy an object to pass it as an argument to a function.
Nikos Athanasiou gave a good answer but I wanted to add this tool that I think is very useful.
Here is a screenshot of Howard Hinnant's presentation "Everything You Ever Wanted To Know About Move Semantics (and then some)" from ACCU 2014 conference which I think is a very good reminder of the rules of automatic generation of special members:
Clarification from Mr Hinnant from the comments:
The slide doesn't say it, but the red squares indicate deprecated behavior. I.e. if you don't want to depend upon deprecated behavior, then declare both of your copy members if you declare your destructor, or one of the copy members (basically follow the C++98/03 "rule of 3")
I recommend reading the slides to get the progressive construction of this table and have a detailed explanation of how and why we have this now.
Other presentations can be found there: http://accu.org/index.php/articles/1901
From the standard Ch. 12 - Special member functions
Par 12.8 Copying and moving class objects (emphasis mine)
9 . If the definition of a class X does not explicitly declare a move constructor, 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 ]
Then 11
explains the rules for deleting the defaulted move constructor
11 . An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/ move constructor for a class X is defined as deleted (8.4.3) if X has:
— a variant member with a non-trivial corresponding constructor and X is a union-like class,
— a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
— a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as applied to B’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
— any direct or virtual base class or non-static data member of a type with a destructor that is deleted or inaccessible from the defaulted constructor, or,
— for the copy constructor, a non-static data member of rvalue reference type. A defaulted move constructor that is defined as deleted is ignored by overload resolution (13.3, 13.4).
[ Note: A deleted move constructor would otherwise interfere with initialization from an rvalue which can use the copy constructor instead. —end note ]
The rules can be somewhat overwhelming. It's good to use some technique to bypass the complexity. Examples are :
* points made in the comments by myself (1) and dyp (2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With