Условия для автоматической генерации оператора по умолчанию / копирования / перемещения ctor и оператора копирования / перемещения?

Я хочу обновить память в условиях, при которых компилятор обычно автоматически генерирует конструктор по умолчанию, конструктор копирования и оператор присваивания.

Я помню, что были некоторые правила, но я не помню, а также не могу найти авторитетный ресурс в Интернете. Кто-нибудь может помочь?

3 ответа

Решение

Далее "автоматически сгенерированный" означает "неявно объявленный как дефолтный, но не определенный как удаленный". Существуют ситуации, когда специальные функции-члены объявляются, но определяются как удаленные.

  • Конструктор по умолчанию генерируется автоматически, если нет объявленного пользователем конструктора (§12.1/5).
  • Конструктор копирования генерируется автоматически, если нет объявленного пользователем конструктора перемещения или оператора присваивания перемещения (поскольку в C++03 нет конструкторов перемещения или операторов перемещения, это упрощается до "всегда" в C++03) (§12.8/8).
  • Оператор присваивания копии генерируется автоматически, если нет объявленного пользователем конструктора перемещения или оператора присваивания перемещения (§12.8/19).
  • Деструктор генерируется автоматически, если деструктор не объявлен пользователем (§12.4/4).

Только C++11 и более поздние версии:

  • Конструктор перемещения генерируется автоматически, если нет объявленного пользователем конструктора копирования, оператора назначения копирования или деструктора и если сгенерированный конструктор перемещения действителен (§12.8/10).
  • Оператор назначения перемещения генерируется автоматически, если нет объявленного пользователем конструктора копирования, оператора назначения копирования или деструктора, и если созданный оператор назначения перемещения действителен (например, если ему не нужно назначать постоянные члены) (§12.8/21).

Я нашел диаграмму ниже очень полезной.

Правила C++ для автоматических конструкторов и операторов присваивания из Sticky Bits - стать правилом нулевого героя

C++17 N4659 стандартная версия

Для быстрой перекрестной ссылки на стандарт ознакомьтесь с разделами "Неявно объявленные" следующих записей cppreference:

Эту же информацию, конечно, можно получить из стандарта. Например, на C++17 N4659 стандартная версия:

15.8.1 "Копирование / перемещение конструкторов" говорит для конструктора копирования:

6 Если определение класса явно не объявляет конструктор копирования, неявный объявляется неявно. Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный конструктор копирования определяется как удаленный; в противном случае он определяется как дефолтный (11.4). Последний случай считается устаревшим, если в классе есть объявленный пользователем оператор копирования или объявленный пользователем деструктор.

и для перемещения конструктора:

8 Если определение класса X явно не объявляет конструктор перемещения, неявный неявно будет объявлен как дефолтный, если и только если

  • (8.1) - X не имеет объявленного пользователем конструктора копирования,

  • (8.2) - X не имеет заявленного пользователем оператора копирования,

  • (8.3) - X не имеет объявленного пользователем оператора назначения перемещения, и

  • (8.4) - X не имеет объявленного пользователем деструктора.

15.8.2 "Оператор назначения копирования / перемещения" говорит для назначения копирования:

2 Если определение класса явно не объявляет оператор присваивания копии, он объявляется неявно. Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный оператор присваивания копии определяется как удаленный; в противном случае он определяется как дефолтный (11.4). Последний случай считается устаревшим, если в классе имеется объявленный пользователем конструктор копирования или объявленный пользователем деструктор.

и для назначения хода:

4 Если определение класса X явно не объявляет оператор присваивания перемещения, он будет неявно объявлен как дефолтный, если и только если

  • (4.1) - X не имеет объявленного пользователем конструктора копирования,
  • (4.2) - X не имеет объявленного пользователем конструктора перемещения,
  • (4.3) - X не имеет объявленного пользователем оператора копирования, и
  • (4.4) - X не имеет объявленного пользователем деструктора.

15.4 "Деструкторы" говорят это для деструкторов:

4 Если в классе нет объявленного пользователем деструктора, деструктор неявно объявляется как дефолтный (11.4). Неявно объявленный деструктор является встроенным публичным членом своего класса.