Страницы

Поиск по вопросам

среда, 15 мая 2019 г.

C++ добавление (= default/delete) в конце функции

Описывается, что если указать void func() = delete/default, то это указывает, что компилятор сам должен сгенерировать код для этой функции и именно он будет использоваться.
Момент с генерацией кода компилятором совсем не понятный. Может кто объяснить доступным языком, что именно за код будет сгенерирован, что это означает и что использовалось до того как появились = default/delete? кроме того, если я допишу в конце деструктора = default, это будет означать, что он виртуальный?


Ответ

Определение функции как default возможно только для специальных функций-членов класса: конструкторов, деструкторов и операторов присваивания. Определяться эти функции будут так, как они неявно определялись испокон веков - через делегирование соответствующих действий каждому полю класса. Произвольную постороннюю функцию нельзя просто взять и определить, как default
Польза от возможности такого определения происходит в первую очередь из того, что в С++11 явное объявление перемещающего конструктора копирования или оператора присваивания подавляет неявное объявление/определение всех остальных функций из Правила Пяти (и наоборот). А в будущем объявление вообще любой функции из Правила Пяти будет подавлять объявление всех остальных функций Правила Пяти. Чтобы в такой ситуации "спасти" потерянные объявления/определения (если они вас устраивают) как раз и подходит default
struct S { S& operator =(S &&) { return *this; } // Подавляет неявное объявление копирующего оператора присваивания };
int main() { S s, t; s = t; // Ошибка - нет копирующего оператора присваивания }
Чтобы "восстановить" работоспособность этого кода достаточно добавить в класс
S& operator =(const S&) = default;
Некоторые тонкости зависят от того, где именно функция определена как default. Если такое определение сделано в точке первого объявления в классе, то такая функция ничем не отличается от неявно определенной функции - она не считается предоставленной пользователем (user-provided). А вот если функция была сначала объявлена в классе, а затем определена как default за пределами класса, то такая функция является предоставленной пользователем. Это влияет на такие свойства класса, как агрегатность и пр.
struct S { int i; S() = default; };
struct T { int i; T(); };
T::T() = default;
// Класс `S` по-прежнему является агрегатом, а вот класс `T` // агрегатом не является
int main() { S s = { 1 }; // Все в порядке, обычная агрегатная инициализация T t = { 1 }; // Ошибка, агрегатная инициализация недоступна }
Описание деструктора как default никак не влияет на его виртуальность.
Определение как delete возможно для любых функций, но с этим такого вопроса не возникает.

Комментариев нет:

Отправить комментарий