Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?
In the following, "auto-generated" means "implicitly declared as defaulted, but not defined as deleted". There are situations where the special member functions are declared, but defined as deleted.
- The default constructor is auto-generated if there is no user-declared constructor (§12.1/5).
- The copy constructor is auto-generated if there is no user-declared move constructor or move assignment operator (because there are no move constructors or move assignment operators in C++03, this simplifies to "always" in C++03) (§12.8/8).
- The copy assignment operator is auto-generated if there is no user-declared move constructor or move assignment operator (§12.8/19).
- The destructor is auto-generated if there is no user-declared destructor (§12.4/4).
C++11 and later only:
- The move constructor is auto-generated if there is no user-declared copy constructor, copy assignment operator or destructor, and if the generated move constructor is valid (§12.8/10).
- The move assignment operator is auto-generated if there is no user-declared copy constructor, copy assignment operator or destructor, and if the generated move assignment operator is valid (e.g. if it wouldn't need to assign constant members) (§12.8/21).
What are the rules for automatic generation of move operations?
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 ]
On the complexity of it all *
The rules can be somewhat overwhelming. It's good to use some technique to bypass the complexity. Examples are :
- Make use of the rule of zero to simplify the writing of the majority of your classes.
- (On implicitly deleted) Explicitly default the special member function in question; if it would have been implicitly defined as deleted, the compiler will complain.
* points made in the comments by myself (1) and dyp (2)
c++ move constructor generated with default constructor
It is nothing related to the move constructor It is about the default constructor. Try this:
class Y
{
public:
Y(const Y&) {}
};
struct hasY {
hasY() = default;
hasY(hasY&&) = default;
Y mem;
};
hasY hy; // This will cause an error because there is no default constructor
Now if you add the default constructor: Y(){}
, the error will go away.
As @M.M commented, The copy constructor will be called in a such case.
You may try this code:
class Y{
public:
Y(){std::cout << "Default constructor\n";}
Y(const Y&) {std::cout << "Copy constructor\n";}
};
struct hasY {
hasY() = default;
hasY(hasY&&) = default;
Y mem;
};
int main(){
hasY hy;
hasY h=std::move(hy);
}
It will print:
Default constructor
Copy constructor
If you want to make the class not moveable you should delete the move constructor by yourself Y(Y&&)=delete;
Conditions under which compiler will not define implicits (constructor, destructor, copy constructor, copy assignment) [duplicate]
The Default Constuctor (e.g., X()
) will not be implicitly generated if:
- you have explicitly declared any constructor at all
- there is a data member that is not default-constructible (such as a reference, a
const
object, or a class with no or inaccessible default constructor) - (C++11) you have explicitly told the compiler to not generate one using
X() = delete;
The Copy Constructor (e.g., X(const X&)
) will not be implicitly generated if:
- you have explicitly declared a copy constructor (for class
X
a constructor takingX
,X&
orconst X&
) - there is a data member that is not copy-constructible (such as a class with no or inaccessible copy constructor)
- the base class is not copy-constructible
- (C++11) you have declared a move constructor or move assignment operator
- (C++11) you have explicitly told the compiler to not generate one using
X(const X&) = delete;
The Copy Assignment Operator (e.g., X& operator=(const X&)
) will not be implicitly generated if:
- you have explicitly declared a copy assignment operator (for class
X
anoperator=
takingX
,X&
orconst X&
) - there is a data member in your class that is not copy-assignable (such as a reference, a
const
object, or a class with no or inaccessible assignment operator) - the base class is not copy-assignable
- (C++11) you have declared a move constructor or move assignment operator
- (C++11) you have explicitly told the compiler to not generate one using
X& operator=(const X&) = delete;
The Destructor (e.g., ~X()
) will not be implicitly generated if:
- you have explicitly declared a destructor
- (C++11) you have explicitly told the compiler to not generate one using
~X() = delete;
The Move Constructor (C++11) (e.g., X(X&&)
) will not be implicitly generated if:
- you have explicitly declared a move constructor (for class
X
, a constructor takingX&&
) - you have declared a copy assignment operator, copy constructor, destructor, or move assignment operator
- there is a data member in your class that cannot be move-constructed (is
const
, is a reference, or has a deleted, inaccessible, or ambiguous move constructor) - the base class cannot be move-constructed
- you have explicitly told the compiler to not generate one using
X(X&&) = delete;
The Move Assignment Operator (C++11) (e.g., X& operator=(X&&)
) will not be implicitly generated if:
- you have explicitly declared a move assignment operator (for class
X
, anoperator=
takingX&&
) - you have declared a copy assignment operator, copy constructor, destructor, or move constructor
- there is a data member in your class that cannot be move-assigned (is
const
, is a reference, or has a deleted, inaccessible, or ambiguous move assignment operator) - the base class cannot be move-assigned
- you have explicitly told the compiler to not generate one using
X& operator=(X&&) = delete;
operator + need Move Constructors
A elision optimisation is permitted here (NRVO) but the object must still be semantically copyable/moveable; by deleting the move constructor, you also deleted the copy constructor, so neither operation is valid and the program is ill-formed.
You can add the copy ctor back:
poo(const poo&) = default;
(And, even if you were using C++17, its guaranteed elision doesn't apply to lvalues.)
Implicit copy constructor in presence of user-defined move constructor/assignment [duplicate]
At least as of the draft I have handiest at the moment (N4618), it's at §[class.copy.ctor]/6:
If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4).
Related Topics
Why Should I Always Enable Compiler Warnings
Do the Parentheses After the Type Name Make a Difference With New
How to Get a Stack Trace for C++ Using Gcc With Line Number Information
Automatically Refreshing a Qtableview When Data Changed
Why Do We Need Virtual Functions in C++
What Are the Differences Between Struct and Class in C++
What Is the Most Effective Way For Float and Double Comparison
Is It a Good Idea to Typedef Pointers
What Are the Rules About Using an Underscore in a C++ Identifier
What Is Array to Pointer Decay
How to Profile C++ Code Running on Linux
Why Do I Have to Access Template Base Class Members Through the This Pointer
Is Short-Circuiting Logical Operators Mandated? and Evaluation Order
How to Instantiate Objects from a String Holding Their Class Name