What does "default" mean after a class' function declaration?
Asked Answered
P

5

304

I've seen default used next to function declarations in a class. What does it do?

class C {
  C(const C&) = default;
  C(C&&) = default;
  C& operator=(const C&) & = default;
  C& operator=(C&&) & = default;
  virtual ~C() { }
};
Pasquale answered 28/6, 2011 at 7:6 Comment(2)
What does the "&" that precedes the "=" in the assignment operator declarations do?Cletis
@Cletis This is a ref-qualification of a member function.Bullnecked
K
346

It's a new C++11 feature.

It means that you want to use the compiler-generated version of that function, so you don't need to specify a body.

You can also use = delete to specify that you don't want the compiler to generate that function automatically.

With the introduction of move constructors and move assignment operators, the rules for when automatic versions of constructors, destructors and assignment operators are generated has become quite complex. Using = default and = delete makes things easier as you don't need to remember the rules: you just say what you want to happen.

Kcal answered 28/6, 2011 at 7:8 Comment(4)
= delete is stronger: It means, using that function is forbidden, though it still takes part in overload resolution.Incorporator
But, if we want to use compiler generate definition, then shouldn't we skip writing that function instead of "first writing it and then assigning it to default"?Martsen
@Mayank Jindal because compiler will bark if we don't provide the no argument constructor, if we have already given the parameterized constructor. In that case, there is no way to skip the declaration of default constructor.Consistence
"compiler-generated version of that function" does this mean an empty body?Conjure
E
59

This is a new C++0x feature that tells the compiler to create the default version of the respective constructor or assignment operator, i.e. the one which just performs the copy or move action for each member. This is useful because the move constructor isn't always generated by default (e.g. if you have a custom destructor), unlike the copy constructor (and likewise for assignment), but if there's nothing non-trivial to write, it's better to let the compiler handle it than to spell it out yourself each time.

Also notice that a default constructor would not be generated if you provide any other non-default constructor. If you still want the default constructor, too, you can use this syntax to have the compiler make one.

As another use case, there are several situations in which a copy constructor would not be generated implicitly (e.g. if you provide a custom move constructor). If you still want the default version, you can request it with this syntax.

See Section 12.8 of the standard for details.

Ethiopic answered 28/6, 2011 at 7:9 Comment(1)
Though it is not only for constructors and assignments, but also applies to operator new/new[], operator delete/delete[] and their overloads.Ghostly
A
23

It is new in C++11, see here. It can be quite useful if you have defined one constructor, but want to use defaults for the others. Pre-C++11 you'd have to define all constructors once you have defined one, even if they are equivalent to the defaults.

Also note that in certain situations it is impossible to provide a user defined default constructor that behaves the same as the compiler synthesized one under both default and value initialization. default allows you to get that behaviour back.

Accepted answered 28/6, 2011 at 7:10 Comment(1)
regarding the second paragraph, can you provide an example?Aaren
C
12

Another use case that I do not see mentioned in these answers is that it easily allows you to change the visibility of a constructor. For example, maybe you want a friend class to be able to access the copy constructor, but you don't want it to be publicly available.

Cletis answered 5/1, 2016 at 6:25 Comment(0)
O
3

C++17 N4659 standard draft

https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2 "Explicitly-defaulted functions":

1 A function definition of the form:

attribute-specifier-seq opt decl-specifier-seq opt declarator virt-specifier-seq opt = default ;

is called an explicitly-defaulted definition. A function that is explicitly defaulted shall

  • (1.1) — be a special member function,

  • (1.2) — have the same declared function type (except for possibly differing ref-qualifiers and except that in the case of a copy constructor or copy assignment operator, the parameter type may be “reference to non-const T”, where T is the name of the member function’s class) as if it had been implicitly declared, and

  • (1.3) — not have default arguments.

2 An explicitly-defaulted function that is not defined as deleted may be declared constexpr only if it would have been implicitly declared as constexpr. If a function is explicitly defaulted on its first declaration, it is implicitly considered to be constexpr if the implicit declaration would be.

3 If a function that is explicitly defaulted is declared with a noexcept-specifier that does not produce the same exception specification as the implicit declaration (18.4), then

  • (3.1) — if the function is explicitly defaulted on its first declaration, it is defined as deleted;

  • (3.2) — otherwise, the program is ill-formed.

4 [ Example:

struct S {
  constexpr S() = default;            // ill-formed: implicit S() is not constexpr
  S(int a = 0) = default;             // ill-formed: default argument
  void operator=(const S&) = default; // ill-formed: non-matching return type
  ~ S() noexcept(false) = default;    // deleted: exception specification does not match
private:
  int i;                              // OK: private copy constructor
  S(S&);
};
S::S(S&) = default;                   // OK: defines copy constructor

— end example ]

5 Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them (15.1 15.4, 15.8), which might mean defining them as deleted. A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [ Note: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note ]

6 [ Example:

struct trivial {
  trivial() = default;
  trivial(const trivial&) = default;
  trivial(trivial&&) = default;
  trivial& operator=(const trivial&) = default;
  trivial& operator=(trivial&&) = default;
  ~ trivial() = default;
};
struct nontrivial1 {
  nontrivial1();
};
nontrivial1::nontrivial1() = default;       // not first declaration

— end example ]

Then the question is of course which functions can be implicitly declared and when does that happen, which I have explained at:

Oriel answered 15/11, 2018 at 10:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.