Умови автоматичного генерування замовчувача / копіювання / переміщення ctor та оператора присвоєння копії / переміщення?


127

Я хочу оновити свою пам’ять про умови, за яких компілятор, як правило, автоматично генерує конструктор за замовчуванням, конструктор копій та оператор призначення.

Я пам’ятаю, були деякі правила, але я не пам’ятаю і також не можу знайти авторитетний ресурс в Інтернеті. Хтось може допомогти?

Відповіді:


136

Далі "автоматично згенерований" означає "неявно оголошений як дефолт, але не визначений як видалений". Бувають ситуації, коли функції спеціальних членів оголошуються, але визначаються як видалені.

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

C ++ 11 і пізніші версії:

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

9
Чи зараховується спадковий деструктор? Я маю на увазі, скажімо, у мене базовий клас із порожнім віртуальним деструктором. Чи заважає це створювати конструктори переміщення в підкласах? Якщо відповідь "так", чи допоможе це, якщо я визначу конструктор переміщення в базовому класі?
kamilk

10
Я думаю, що ви можете згадати, можливо, те, що наявність constчленів у класі запобіжить автоматичному формуванню конструктора ...
nonsensickle

Чи "Є ситуації, коли функції спеціального члена оголошуються, але визначаються як видалені." посилайтеся на те, де у вас, наприклад, є const або довідкові члени, де переміщення буде неможливо? Ні, цього не може бути, тому що там буде застосована копія.
буксі

Я знаю, що надсилати гіперпосилання на цей форум обмежено. Але це також гарна стаття - cplusplus.com/articles/y8hv0pDG
bruziuz

Зауважимо, що, як правило, неявно дефолтний конструктор копій " є застарілим, якщо у класу є оголошений користувачем оператор присвоєння копії або оголошений користувачем деструктор " ( 12.8 Копіювання та переміщення об'єктів класу [class.copy] ).
sigy

98

Діаграма нижче я вважаю дуже корисною.

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


Гарний. Що означає "незалежний"? Незалежний від чого?
букси

8
Копіювати ctor / завдання є "незалежними" один від одного. Якщо ви пишете лише одне, компілятор надасть інший. На противагу цьому, якщо ви надаєте або ctor переміщення, або призначення переміщення, компілятор не надасть іншого.
Марко М.

Цікаво, в чому причина операцій з копіюванням незалежності. Історичні причини можуть бути? чи той факт, що копія не змінює цільову, але переміщення робить?
RaGa__M

@Explorer_N Так, відстала сумісність, тому історичні причини. Давно це був поганий вибір дизайну, тому зараз є потреба в належній практиці, як "правило трьох" (визначте всі 3 чи жодні: конструктор копій, оператор призначення копії та часто деструктор), щоб уникнути важких помилок.
атаблаш

@MarcoM., Наскільки я зрозумів, умова "Якщо ти пишеш ..." включає два випадки встановлення функції спеціального члена на = delete(очевидно) або = default(менш очевидно для мене). Маю рацію?
Енріко Марія Де Анджеліс

2

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). Явно декларований деструктор - це вбудований громадський член свого класу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.