135

I want to refresh my memory on the conditions under which a compiler typically auto generates a default constructor, copy constructor and assignment operator.

I recollect there were some rules, but I don't remember, and also can't find a reputable resource online. Can anyone help?

Community
  • 1
  • 1
oompahloompah
  • 8,321
  • 18
  • 59
  • 89

3 Answers3

142

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).
milleniumbug
  • 14,714
  • 3
  • 43
  • 70
Philipp
  • 43,805
  • 12
  • 78
  • 104
  • 10
    Does an inherited destructor count? I mean, say I've got a base class with an empty virtual destructor. Does it prevent creation of move constructors in subclasses? If the answer is yes, will it help if I define a move constructor in the base class? – kamilk Jul 06 '14 at 13:29
  • 10
    I think that you should mention perhaps that having `const` members in the class will prevent the constructor from being auto-generated... – nonsensickle Jul 31 '14 at 23:08
  • Does "There are situations where the special member functions are declared, but defined as deleted." refer to where you for example have const or reference members where move will be impossible? No, that can't be, because there copy will be applied. – towi Sep 27 '16 at 07:37
  • 1
    I know that it's restricted to send hyperlinks in this forum. But it's also good article - http://www.cplusplus.com/articles/y8hv0pDG/ – bruziuz Oct 12 '16 at 00:54
  • Note, that as of the standard an implicitly defaulted copy constructor "_is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor_" (**12.8 Copying and moving class objects [class.copy]**). – sigy Mar 29 '17 at 10:59
112

I've found the diagram below very useful.

C++ rules for automatic constructors and assignment operators from Sticky Bits - Becoming a Rule of Zero Hero

O'Neil
  • 3,638
  • 3
  • 13
  • 28
Marco M.
  • 2,559
  • 2
  • 25
  • 21
  • Beautiful. What does "independent" refer to? Independent from what? – towi Sep 27 '16 at 07:29
  • 8
    Copy ctor/assignment are 'independent' from each other. If you write just one, the compiler will provide the other. In contrast, if you provide either a move ctor or a move assignment, the compiler won't supply the other. – Marco M. Oct 03 '16 at 20:14
  • Wonder what's the reason behind copy operations are being independent. Historic reasons may be? or the fact that copy won't modify it's target but move does? – RaGa__M Jul 05 '17 at 07:47
  • @Explorer_N Yes, backward compatibility, so historic reasons. It was a bad design choice long time ago, so now there's a need for good practices like the "rule of three" (define all 3 or none: copy constructor, copy assignment operator, and often destructor) to avoid hard to find bugs. – atablash Mar 31 '18 at 18:41
  • 1
    @MarcoM., as far as I've understood, the "If you write..." condition includes the two cases of setting the special member function to `= delete` (obvious) or `= default` (less obvious to me). Am I right? – Enlico May 19 '19 at 12:46
3

C++17 N4659 standard draft

For a quick cross standard reference, have a look at the "Implicitly-declared" sections of the following cppreference entries:

The same information can of course be obtained from the standard. E.g. on C++17 N4659 standard draft:

15.8.1 "Copy/move constructors" says for for copy constructor:

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 (11.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

and for move constructor:

8 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

  • (8.1) — X does not have a user-declared copy constructor,

  • (8.2) — X does not have a user-declared copy assignment operator,

  • (8.3) — X does not have a user-declared move assignment operator, and

  • (8.4) — X does not have a user-declared destructor.

15.8.2 "Copy/move assignment operator" says for copy assignment:

2 If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defined as defaulted (11.4). The latter case is deprecated if the class has a user-declared copy constructor or a user-declared destructor.

and for move assignment:

4 If the definition of a class X does not explicitly declare a move assignment operator, one will be implicitly declared as defaulted if and only if

  • (4.1) — X does not have a user-declared copy constructor,
  • (4.2) — X does not have a user-declared move constructor,
  • (4.3) — X does not have a user-declared copy assignment operator, and
  • (4.4) — X does not have a user-declared destructor.

15.4 "Destructors" says it for destructors:

4 If a class has no user-declared destructor, a destructor is implicitly declared as defaulted (11.4). An implicitly-declared destructor is an inline public member of its class.