Условия для автоматической генерации оператора по умолчанию / копирования / перемещения 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++17 N4659 стандартная версия
Для быстрой перекрестной ссылки на стандарт ознакомьтесь с разделами "Неявно объявленные" следующих записей cppreference:
- https://en.cppreference.com/w/cpp/language/copy_constructor
- https://en.cppreference.com/w/cpp/language/move_constructor
- https://en.cppreference.com/w/cpp/language/copy_assignment
- https://en.cppreference.com/w/cpp/language/move_assignment
Эту же информацию, конечно, можно получить из стандарта. Например, на 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). Неявно объявленный деструктор является встроенным публичным членом своего класса.