NoCopy() = default; //
//
NoCopy(const NoCopy&) = delete; //
NoCopy &operator=(const NoCopy&) = delete; //
~NoCopy() = default; //
//
};
Часть = delete указывает компилятору (и читателям кода), что эти функции-члены не определяются
В отличие от части = default, часть = delete должна присутствовать в первом объявлении удаленной функции. Это различие согласуется со смыслом данных объявлений. Часть = default влияет только на то, какой код создает компилятор; следовательно, она необходима, только пока компилятор не создаст код. С другой стороны, компилятор должен знать, что функция удалена, и запретить ее использование другими функциями.
Также в отличие от части = default, часть = delete можно применить для любой функции (= default применима только к стандартному конструктору или функции-члену управления копированием, которую компилятор может синтезировать). Хотя изначально удаленные функции предназначались для подавления функций-членов управления копированием, они иногда применимы также для воздействия на процесс подбора функции.
Следует заметить, что удалять деструктор нельзя. Если его удалить, то не будет никакого способа освободить объект этого типа. Компилятор не позволит определять переменные или создавать временные объекты типа, у которого удален деструктор. Кроме того, нельзя определять переменные или временные объекты класса, обладающего членом, у типа которого удален деструктор. Если у переменной-члена класса удален деструктор, то она не может быть освобождена. Если не может быть удалена переменная-член, не может быть удален и весь объект в целом.
Хотя определить переменные или переменные-члены таких типов нельзя, вполне можно динамически резервировать объекты с удаленным деструктором. Однако впоследствии их нельзя будет освободить:
struct NoDtor {
NoDtor() = default; //
//
~NoDtor() = delete; //
};
NoDtor nd; //
NoDtor *p = new NoDtor(); //
delete p; //
Как уже упоминалось, если не определены функции-члены управления копированием, компилятор определит их сам. Аналогично, если класс не определяет конструктор, компилятор синтезирует стандартный конструктор для этого класса сам (см. раздел 7.1.4). Для некоторых классов компилятор определяет эти синтезируемые функции-члены как удаленные.
• Синтезируемый деструктор определяется как удаленный, если у класса есть переменная-член, собственный деструктор которой удален или недоступен (например, private).
• Синтезируемый конструктор копий определяется как удаленный, если у класса есть переменная-член, собственный деструктор которой удален или недоступен. Он также будет удаленным, если у класса есть переменная-член с удаленным или недоступным деструктором.
• Синтезируемый оператор присвоения копии определяется как удаленный, если у класса есть переменная-член с удаленным или недоступным оператором присвоения копии, либо если у класса есть константный или ссылочный член.
• Синтезируемый стандартный конструктор определяется как удаленный, если у класса есть переменная-член с удаленным или недоступным деструктором; или имеется ссылочный член без внутриклассового инициализатора (см. раздел 2.6.1); или есть константная переменная-член, тип которой не определяет стандартный конструктор явно и не имеет внутриклассового инициализатора.
Короче говоря, эти правила означают, что если у класса есть переменная-член, которая не может быть стандартно создана, скопирована, присвоена или удалена, то соответствующая функция-член класса будет удаленной функцией.
Как ни удивительно, но переменная-член, класс которой имеет удаленный или недоступный деструктор, приводит к определению синтезируемого стандартного конструктора копий удаленным. Основание для этого правила в том, что без него возможно создание объектов, которые невозможно удалить.