Что означает "default" после объявления функции класса?

Я видел default, используемый рядом с объявлениями функций в классе. Что он делает?

class C {
  C(const C&) = default;
  C(C&&) = default;
  C& operator=(const C&) & = default;
  C& operator=(C&&) & = default;
  virtual ~C() { }
};

Ответ 1

Это новая функция С++ 11.

Это означает, что вы хотите использовать сгенерированную компилятором версию этой функции, поэтому вам не нужно указывать тело.

Вы также можете использовать = delete, чтобы указать, что вы не хотите, чтобы компилятор автоматически сгенерировал эту функцию.

С введением конструкторов перемещения и операторов переадресации правила, когда генерируются автоматические версии конструкторов, деструкторов и операторов присваивания, стали довольно сложными. Использование = default и = delete упрощает работу, так как вам не нужно запоминать правила: вы просто говорите, что хотите.

Ответ 2

Это новая функция С++ 0x, которая сообщает компилятору создать стандартную версию соответствующего конструктора или оператора присваивания, то есть тот, который просто выполняет операцию копирования или перемещения для каждого члена. Это полезно, потому что конструктор перемещения не всегда генерируется по умолчанию (например, если у вас есть пользовательский деструктор), в отличие от конструктора копирования (а также для назначения), но если нет ничего нетривиального для записи, лучше компилятор обрабатывает его, а не каждый раз произносить его.

Также обратите внимание, что конструктор по умолчанию не будет сгенерирован, если вы предоставите любой другой конструктор, отличный от стандартного. Если вам по-прежнему нужен конструктор по умолчанию, вы также можете использовать этот синтаксис для компилятора.

В качестве другого варианта использования существует несколько ситуаций, в которых конструктор копирования не будет генерироваться неявно (например, если вы предоставляете собственный конструктор перемещения). Если вам по-прежнему нужна версия по умолчанию, вы можете запросить ее с помощью этого синтаксиса.

Подробнее см. раздел 12.8 стандарта.

Ответ 3

Это новое в С++ 11, смотрите здесь. Это может быть очень полезно, если вы определили один конструктор, но хотите использовать значения по умолчанию для других. До С++ 11 вам нужно было бы определить все конструкторы, как только вы их определили, даже если они эквивалентны значениям по умолчанию.

Также обратите внимание, что в определенных ситуациях невозможно предоставить определяемый пользователем конструктор по умолчанию, который ведет себя так же, как конструктор, синтезированный компилятором, при инициализации по умолчанию и по умолчанию. default позволяет вам вернуть это поведение.

Ответ 4

Другой вариант использования, который я не вижу в этих ответах, заключается в том, что он легко позволяет изменять видимость конструктора. Например, возможно, вы хотите, чтобы класс друга мог получить доступ к конструктору копирования, но вы не хотите, чтобы он был общедоступным.

Ответ 5

С++ 17 N4659 стандартный черновик

https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf  11.4.2 "Явно-дефолтные функции":

1 Определение функции формы:

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

называется явно заданным по умолчанию определением. Функция, которая явно установлена по умолчанию, должна

  • (1.1) — be a special member function,

  • (1.2) - иметь один и тот же объявленный тип функции (за исключением, возможно, различных ref-квалификаторов и за исключением того, что в В случае конструктора копирования или оператора назначения копирования тип параметра может быть "ссылкой на неконстантный T ', где T - имя класса функций-членов), как если бы он был неявно объявлен, и

  • (1.3) — not have default arguments.

2 Явно дефолтная функция, которая не определена как удаленная, может быть объявлена constexpr, только если она были неявно объявлены как constexpr. Если функция явно установлена по умолчанию в своем первом объявлении, она неявно считается constexpr, если неявное объявление будет.

3 Если функция с явным значением по умолчанию объявлена с указателем noexcept, который не выдает то же самое спецификация исключения как неявное объявление (18.4), затем

  • (3.1) - если функция явно установлена по умолчанию в своем первом объявлении, она определяется как удаленная;

  • (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 Явно-дефолтные функции и неявно-объявленные функции вместе называются дефолтными функциями, и реализация должна предоставить для них неявные определения (15.1, 15.4, 15.8), что может означать определение они как удалены. Функция предоставляется пользователем, если она объявлена пользователем и не имеет явных значений по умолчанию или удалена на своей первой декларации. Предоставленная пользователем явно дефолтная функция (т.е. явно дефолтная после ее первого декларация) определяется в том месте, где оно явно не выполнено; если такая функция неявно определяется как удален, программа некорректна [Примечание: объявление функции по умолчанию после ее первого объявления может обеспечить эффективное выполнение и четкое определение, обеспечивая в то же время стабильный двоичный интерфейс для развивающегося кода база. - конец примечания]

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 ]

Тогда вопрос, конечно, в том, какие функции могут быть неявно объявлены и когда это происходит, что я объяснил на: