Удаление конструктора копирования
Есть класс
class CTest {
public:
CTest() {};
CTest(const CTest & src) = delete;
};
и есть код
CTest t1, t2;
t1 = t2;
вопрос: почему код компилируется? Ведь я удаляю конструктор копирования, а значит присваивание должно быть запрещено.
Update:
Ошибка появляется при удалении оператора присваивания
CTest & operator=(const CTest &) = delete;
получается, что при присвоении конструктор копирования не вызывается?
Ответы (1 шт):
Если бы вы написали
CTest t2;
CTest t1 = t2;
то тогда это было бы конструирование копированием, а так - у вас объект уже создан, и это - присваивание, а не копирование.
Вызывается ли при присваивании конструктор копирования? В общем случае нет - если вы не вызываете его сами.
Должен ли в 99% случаев копирующий конструктор совпадать с присваиванием? Только если в 99% случаев не требуется деструктор :) Ведь при копировании объекта еще нет, а при присваивании - уже есть, и его сначала надо удалить.
Но именно из-за схожести копирования и присваивания часто используется идиома присваивания через обмен с копией. Если вы можете написать функцию обмена внутреннего содержимого классов, типа
class A {
...
private:
void swap(A&);
которая обменивает содержимое двух объектов - вашего и переданного как аргумент, и у вас есть конструктор копирования
A::A(const A&)
то оператор присваивания можно записать как
A& A::operator=(const A& a)
{
A tmp(a);
swap(tmp);
return *this;
}
Можно для эффективности добавить проверку присваивания себе (хотя она не обязательна)
A& A::operator=(const A& a)
{
if (this != &a)
{
A tmp(a);
swap(tmp);
}
return *this;
}
Можно копирование сделать неявным, при передаче аргумента
A& A::operator=(A a)
{
swap(a);
return *this;
}
Вот при использовании такой идиомы удаление конструктора копирования действительно сделает присваивание невозможным...