The copy constructor is automatically generated when all of the following apply:
The move constructor is automatically generated when all of the following apply:
What it the output?
#include <iostream>
#include <type_traits>
class GeoObj {
public:
GeoObj& operator=(const GeoObj&) { return *this; };
};
int main() {
std::cout << std::boolalpha;
std::cout << std::is_move_constructible<GeoObj>::value << "\n";
}
You may think “false” because of no move constructor based on the standard; however the answer is “true”. Because types without a move constructor, but with a copy constructor that accepts const T& arguments, satisfy std::is_move_constructible. See here for more details.
The copy assignment operator is automatically generated when all of the following apply:7
The move assignment operator is automatically generated when all of the following apply:
Destructors are nothing special with move semantics except that their declaration disables the automatic generation of move operations.
The default constructor (the “not-so-special” special member function) is still automatically generated if no other constructor is declared. That is, the declaration of a move constructor disables the generation of a default constructor.
In C++11, if any base class or member of a class cannot be copied or moved (because its special member function is = delete, private, or otherwise inaccessible), then the compiler automatically defines the corresponding implicitly-declared special member of the derived class as deleted.
When declaring a copying special member function (or the destructor), we have the automatic generation of the moving special member functions disabled.
Because the fallback mechanism works, copying and moving a Person compiles but the move is performed as a copy:
class Person {
public:
// copy constructor/assignment declared:
Person(const Person&) = default;
Person& operator=(const Person&) = default;
// NO move constructor/assignment declared
};
std::vector<Person> coll;
Person p{"Tina", "Fox"};
coll.push_back(p); // OK, copies p
coll.push_back(std::move(p)); // OK, copies p
If you have user-declared move semantics, you have disabled copy semantics. The copying special member functions are deleted.
In other words, if the move constructor or the move assignment operator is explicitly declared (implemented, generated with =default, or disabled with =delete), you have disabled to call the copy constructor and the copy assignment operator by declaring them with =delete.
Assume the following declaration of a class Person:
class Person {
public:
// NO copy constructor declared
// move constructor/assignment declared:
Person(Person&&) = default;
Person& operator=(Person&&) = default;
};
In this case, we have a move-only type. A Person can be moved but not copied:
std::vector<Person> coll;
Person p{"Tina", "Fox"};
coll.push_back(p); // ERROR: copying disabled
coll.push_back(std::move(p)); // OK, moves p
coll.push_back(Person{"Ben", "Cook"}); // OK, moves temporary person into coll
The consequence: the attempt to copy an object will no longer compile.
Deleting the copying special member functions is enough. (Never =delete the special move member functions).
