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

188
01 ноября 2018, 10:50

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

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

Answer 1

Определение функции как 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 возможно для любых функций, но с этим такого вопроса не возникает.

READ ALSO
Для чего нужны мьютексы в C++

Для чего нужны мьютексы в C++

В C++ существет такое понятие, как мьютексыКто может объяснить мне, зачем они нужны?

174
Electronjs вызов функций из c++ модуля

Electronjs вызов функций из c++ модуля

Всем доброго, недавно начал рассматривать варианты использования с++ аддонов из electron js и не особо нашел что хотелДело в том что стандартный...

194
Malloc большого количества данных в си

Malloc большого количества данных в си

У меня скорее вопрос чем проблемаMalloc не выводит ошибки если я пытаюсь выделить 8gb памяти, но на ноутбуке ее всего 6gb

176
Проблема с работой библиотеки <iostream.h> и <conio.h>

Проблема с работой библиотеки <iostream.h> и <conio.h>

Недавно перешел на ubuntu и возникла проблема с работой библиотек "iostreamh" и "conio

174