Classes and class hierarchies
C.80
Используйте `=default` если вы должны явно указать использование семантики по умолчанию
Причина
Компилятор более вероятно получит семантику по умолчанию правильно, и вы не можете реализовать эти функции лучше, чем компилятор.
Пример
class Tracer {
string message;
public:
Tracer(const string& m) : message{m} { cerr << "entering " << message << '\n'; }
~Tracer() { cerr << "exiting " << message << '\n'; }
Tracer(const Tracer&) = default;
Tracer& operator=(const Tracer&) = default;
Tracer(Tracer&&) noexcept = default;
Tracer& operator=(Tracer&&) noexcept = default;
};
Поскольку мы определили деструктор, мы должны определить операции копирования и перемещения. = default — это лучший и простейший способ сделать это.
Плохой пример
class Tracer2 {
string message;
public:
Tracer2(const string& m) : message{m} { cerr << "entering " << message << '\n'; }
~Tracer2() { cerr << "exiting " << message << '\n'; }
Tracer2(const Tracer2& a) : message{a.message} {}
Tracer2& operator=(const Tracer2& a) { message = a.message; return *this; }
Tracer2(Tracer2&& a) noexcept :message{a.message} {}
Tracer2& operator=(Tracer2&& a) noexcept { message = a.message; return *this; }
};
Написание тел операций копирования и перемещения многословно, утомительно и подвержено ошибкам. Компилятор делает это лучше.
Применение
(Умеренно) Тело пользовательской операции не должно иметь ту же семантику, что и версия, сгенерированная компилятором, потому что это было бы избыточно.