Что означает «по умолчанию» после объявления функции класса? - PullRequest
194 голосов
/ 28 июня 2011

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

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

Ответы [ 5 ]

222 голосов
/ 28 июня 2011

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

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

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

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

41 голосов
/ 28 июня 2011

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

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

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

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

20 голосов
/ 28 июня 2011

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

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

11 голосов
/ 05 января 2016

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

0 голосов

C ++ 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) - быть специальной функцией-членом,

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

  • (1.3) - не имеет аргументов по умолчанию.

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

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

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

  • (3.2) - в противном случае программа некорректна.

4 [Пример:

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

- конец примера]

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

6 [Пример:

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

- конец примера]

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

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