Я бачив default
використані поруч із функціями декларацій у класі. Що це робить?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
Я бачив default
використані поруч із функціями декларацій у класі. Що це робить?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
Відповіді:
Це нова функція C ++ 11 .
Це означає, що ви хочете використовувати створену компілятором версію цієї функції, тому вам не потрібно вказувати тіло.
Ви також = delete
можете вказати, що ви не хочете, щоб компілятор автоматично генерував цю функцію.
З впровадженням конструкторів переміщення та операторів присвоєння переміщення правила щодо створення автоматичних версій конструкторів, деструкторів та операторів присвоєння стали досить складними. Використання = default
та = delete
полегшує справи, оскільки вам не потрібно пам’ятати правила: ви просто говорите, що хочете, щоб сталося.
= delete
сильніше: Це означає, що використовувати цю функцію заборонено, хоча вона все ще бере участь у вирішенні перевантаження.
Це нова функція C ++ 0x, яка повідомляє компілятору створити версію за замовчуванням відповідного конструктора або оператора присвоєння, тобто ту, яка щойно виконує дію копіювання або переміщення для кожного члена. Це корисно, оскільки конструктор переміщення не завжди генерується за замовчуванням (наприклад, якщо у вас є спеціальний деструктор), на відміну від конструктора копіювання (і аналогічно для призначення), але якщо немає нічого нетривіального для запису, краще дозволити компілятор впорається з цим, ніж щоразу промальовувати.
Також зауважте, що конструктор за замовчуванням не створюється, якщо ви надаєте будь-який інший конструктор, який не використовується за замовчуванням. Якщо ви все ще хочете конструктора за замовчуванням, ви також можете використовувати цей синтаксис, щоб компілятор зробив його.
Як інший випадок використання, існує кілька ситуацій, коли конструктор копій не створюється неявно (наприклад, якщо ви надаєте користувацький конструктор переміщення). Якщо ви все ще хочете версії за замовчуванням, ви можете надіслати запит на неї за допомогою цього синтаксису.
Детальніше див. Розділ 12.8 стандарту.
operator new/new[]
, operator delete/delete[]
і їх перевантаження.
Він новий у C ++ 11, дивіться тут . Це може бути дуже корисно, якщо ви визначили один конструктор, але хочете використовувати параметри за замовчуванням для інших. Pre-C ++ 11 вам потрібно буде визначити всі конструктори, як тільки ви їх визначили, навіть якщо вони еквівалентні за замовчуванням.
Також зауважте, що в певних ситуаціях неможливо надати визначений користувачем конструктор за замовчуванням, який поводиться так само, як синтезований компілятором, і за ініціалізацією за замовчуванням, і за значенням . default
дозволяє повернути таку поведінку.
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) - мають той самий оголошений тип функції (за винятком можливо різних класифікаторів, за винятком випадків, що стосується конструктора копії або оператора присвоєння копії, тип параметра може бути "посиланням на нестандартний 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
- кінцевий приклад]
Тоді, звичайно, питання, які функції можна неявно оголосити, і коли це відбувається, що я пояснив у: