Условия для автоматического создания оператора по умолчанию / копирования / перемещения и оператора присваивания копирования / перемещения?
127
Я хочу освежить свою память об условиях, при которых компилятор обычно автоматически генерирует конструктор по умолчанию, конструктор копирования и оператор присваивания.
Я припоминаю, что были некоторые правила, но я не помню, а также не могу найти авторитетный ресурс в Интернете. Кто-нибудь может помочь?
Далее «автоматически сгенерированный» означает «неявно объявлен как установленный по умолчанию, но не определен как удаленный». Бывают ситуации, когда специальные функции-члены объявлены, но определены как удаленные.
Конструктор по умолчанию создается автоматически, если конструктор, объявленный пользователем, отсутствует (§12.1 / 5).
Конструктор копирования генерируется автоматически, если нет объявленного пользователем конструктора перемещения или оператора присваивания перемещения (поскольку в C ++ 03 нет конструкторов перемещения или операторов присваивания перемещения, это упрощается до «всегда» в C ++ 03) ( §12.8 / 8).
Оператор присваивания копий генерируется автоматически, если нет объявленного пользователем конструктора перемещения или оператора присваивания перемещения (§12.8 / 19).
Конструктор перемещения создается автоматически, если нет объявленного пользователем конструктора копирования, оператора присваивания копии или деструктора, и если сгенерированный конструктор перемещения действителен (§12.8 / 10).
Оператор присваивания перемещения генерируется автоматически, если нет объявленного пользователем конструктора копирования, оператора присваивания копии или деструктора, и если сгенерированный оператор присваивания перемещения действителен (например, если ему не нужно назначать постоянные члены) (§12.8 / 21).
Считается ли унаследованный деструктор? Я имею в виду, скажем, у меня есть базовый класс с пустым виртуальным деструктором. Предотвращает ли это создание конструкторов перемещения в подклассах? Если да, поможет ли, если я определю конструктор перемещения в базовом классе?
kamilk 06
10
Я думаю, вам следует упомянуть, возможно, наличие constчленов в классе предотвратит автоматическую генерацию конструктора ...
бессонница
Имеет ли «Бывают ситуации, когда специальные функции-члены объявлены, но определены как удаленные». ссылаетесь на то, где у вас, например, есть константные или ссылочные члены, где перемещение будет невозможно? Нет, этого не может быть, потому что копия будет применена.
Обратите внимание, что по стандарту неявно заданный по умолчанию конструктор копирования « устарел, если класс имеет объявленный пользователем оператор присваивания копии или объявленный пользователем деструктор » ( 12.8 Копирование и перемещение объектов класса [class.copy] ).
Прекрасный. Что означает «независимый»? Независимо от чего?
Towi
8
Копирование / назначение «независимы» друг от друга. Если вы напишете только один, компилятор предоставит другой. Напротив, если вы предоставите либо ctor перемещения, либо назначение перемещения, компилятор не предоставит другой.
Марко М.
Интересно, в чем причина того, что операции копирования независимы. Может быть исторические причины? или тот факт, что копия не изменяет цель, а перемещает?
RaGa__M 05
@Explorer_N Да, обратная совместимость, так что исторические причины. Давным-давно это был плохой выбор дизайна, поэтому теперь существует потребность в хороших практиках, таких как «правило трех» (определить все 3 или ничего: конструктор копирования, оператор присваивания копии и часто деструктор), чтобы избежать трудных для поиска ошибок.
atablash
@MarcoM., Насколько я понял, условие «Если вы напишете ...» включает в себя два случая установки специальной функции-члена на = delete(очевидный) или = default(менее очевидный для меня). Я прав?
Энрико Мария Де Анджелис
2
Стандартный проект C ++ 17 N4659
Для быстрой перекрестной ссылки на стандарты взгляните на разделы «Неявно объявленные» следующих записей cppreference:
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). Неявно объявленный деструктор является встроенным публичным членом своего класса.
const
членов в классе предотвратит автоматическую генерацию конструктора ...Я нашел диаграмму ниже очень полезной.
from Sticky Bits - Стать правилом нулевого героя
источник
= delete
(очевидный) или= default
(менее очевидный для меня). Я прав?Стандартный проект C ++ 17 N4659
Для быстрой перекрестной ссылки на стандарты взгляните на разделы «Неявно объявленные» следующих записей cppreference:
Та же информация, конечно, может быть получена из стандарта. Например, на стандартном проекте C ++ 17 N4659 :
15.8.1 «Конструкторы копирования / перемещения» для конструктора копирования:
и для конструктора перемещения:
15.8.2 «Оператор присваивания копирования / перемещения» говорит о назначении копии:
и для переезда:
15.4 «Деструкторы» говорят о деструкторах:
источник