Смысл в том, что если вы обнаружите необходимость объявить деструктор или скопировать специальный член для вашего класса, тогда класс должен содержать ресурсы, которые требуют специальной обработки, поэтому неявное объявление перемещения специальных членов может быть опасным в этом сгенерированном кодеможет привести к некорректному поведению.
Простой пример:
struct String
{
char *s = nullptr;
size_t size = 0;
String(char const* s); // makes a copy of the string
~String()
{
delete[] s;
}
};
Если бы стандарт позволял генерацию неявного конструктора перемещения, что бы он делал?Он просто инициализирует s
и size
в целевом объекте, но не назначит их nullptr
и 0
соответственно в исходном объекте.Это затем приводит к двойному удалению в деструкторе исходного и целевого объекта и неопределенном поведении.
Неявная генерация оператора назначения копирования также приводит к аналогичным проблемам.
Обратите внимание, что C ++11 устарела неявная генерация копии специальных членов, а также для приведенного выше примера.К сожалению, они не могут быть определены как удаленные, потому что это нарушит слишком много кода.
[class.copy.ctor] / 6
Если определение класса явно не объявляет конструктор копирования, неявный объявляется неявно.Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный конструктор копирования определяется как удаленный;в противном случае он определяется как дефолтный. Последний случай считается устаревшим, если в классе есть пользовательский оператор назначения копирования или пользовательский деструктор.