Если параметр operator=
правильно определен, можно ли использовать следующее как конструктор копирования?
MyClass::MyClass(MyClass const &_copy)
{
*this = _copy;
}
Если параметр operator=
правильно определен, можно ли использовать следующее как конструктор копирования?
MyClass::MyClass(MyClass const &_copy)
{
*this = _copy;
}
Если все члены MyClass
имеют конструктор по умолчанию, да.
Обратите внимание, что обычно это наоборот:
class MyClass
{
public:
MyClass(MyClass const&); // Implemented
void swap(MyClass&) throw(); // Implemented
MyClass& operator=(MyClass rhs) { rhs.swap(*this); return *this; }
};
Мы передаем значение в operator=
, чтобы вызвать конструктор копирования. Обратите внимание, что все исключение безопасно, поскольку swap
гарантированно не бросается (вы должны убедиться в этом в своей реализации).
ИЗМЕНИТЬ, в соответствии с запросом, о материалах по умолчанию: operator=
может быть записано как
MyClass& MyClass::operator=(MyClass const& rhs)
{
MyClass tmp(rhs);
tmp.swap(*this);
return *this;
}
Студентам С++ обычно предлагается передавать экземпляры класса по ссылке, потому что конструктор копирования вызывается, если они передаются по значению. В нашем случае нам все равно нужно скопировать rhs
, так что передача по значению в порядке.
Таким образом, operator=
(первая версия, вызов по значению) читает:
rhs
(через автоматически созданный конструктор копирования)*this
*this
и rhs
(который содержит старое значение) будет уничтожен при выходе метода.Теперь у нас есть дополнительный бонус с этим по умолчанию. Если объект, передаваемый operator=
(или любая функция, которая получает свои аргументы по значению), является временным объектом, компилятор может (и обычно делает) вообще не копировать. Это называется копией.
Следовательно, если rhs
является временным, копия не производится. Осталось:
this
и rhs
содержимоеrhs
Таким образом, передача по значению в этом случае более эффективна, чем передача по ссылке.
Более целесообразно реализовать operator = с точки зрения конструктора исключаемых копий. См. Пример 4. в этом от Herb Sutter для объяснения техники и почему это хорошая идея.
Эта реализация подразумевает, что конструкторы по умолчанию для всех членов данных (и базовых классов) доступны и доступны из MyClass, потому что они будут вызваны первыми, прежде чем выполнять назначение. Даже в этом случае наличие дополнительного вызова для конструкторов может быть дорогостоящим (в зависимости от содержания класса).
Я бы по-прежнему придерживался отдельной реализации конструктора копирования через список инициализации, даже если это означает, что нужно написать больше кода.
Другое: эта реализация может иметь побочные эффекты (например, если у вас есть динамически распределенные элементы).
В то время как конечный результат тот же, члены сначала инициализируются по умолчанию, только после этого копируются.
С "дорогим" членом лучше скопировать-конструкцию с помощью списка инициализаторов.
struct C {
ExpensiveType member;
C( const C& other ): member(other.member) {}
};
};
Я бы сказал, что это не нормально, если MyClass
выделяет память или изменяет ее.
да.
лично, если ваш класс не имеет указателей, хотя я бы не перегружал равный оператор или не писал конструктор копирования, и пусть компилятор сделает это за вас; он будет реализовывать неглубокую копию, и вы точно будете знать, что все данные участников скопированы, а если вы перегрузите = op; а затем добавьте элемент данных, а затем забудьте обновить перегрузку, у вас возникнет проблема.
@Alexandre - я не уверен в передаче по значению в операторе присваивания. В чем преимущество, которое вы получите, позвонив в конструктор копирования? Будет ли это закрепление оператора присваивания?
P.S. Я не знаю, как писать комментарии. Или может быть, мне не разрешено писать комментарии.
Это технически нормально, если у вас есть оператор рабочего назначения (оператор копирования).
Однако вы должны предпочесть copy-and-swap, потому что: