Я все еще получаю конструктор копирования по умолчанию и оператор =, если я определяю те с неконстантными аргументами?
В C++, если я определяю конструктор копирования и operator=, которые принимают неконстантную ссылку на класс, должен ли компилятор по-прежнему предоставлять версии по умолчанию для константной ссылки?
struct Test {
Test(Test &rhs);
Test &operator=(Test &rhs);
private:
// Do I still need to declare these to avoid automatic definitions?
Test(const Test &rhs);
Test &operator=(const Test &rhs);
};
2 ответа
Нет, если вы определите конструктор копирования и оператор присваивания, компилятор не будет неявно объявлять или определять свой собственный. Обратите внимание, что определение конструктора копирования позволяет аргументу принимать либо константную, либо неконстантную ссылку, поэтому ваш конструктор действительно является конструктором копирования. Аналогично для operator=
[Опуская большую часть деталей, в частности, при каких обстоятельствах неявно объявленные специальные функции-члены также будут неявно определены]
12.8 [class.copy] / 2 Не шаблонный конструктор для класса X является конструктором копирования, если его первый параметр имеет тип X&, const X&, volatile X& или const volatile X&, и либо нет других параметров, либо все остальные параметры имеют аргументы по умолчанию (8.3.6).
12.8 [class.copy] / 7 Если определение класса явно не объявляет конструктор копирования, он объявляется неявно.
12.8 [class.copy] / 17 Объявленный пользователем оператор присваивания копии X::operator= - это нестатическая не шаблонная функция-член класса X с ровно одним параметром типа X, X&, const X&, volatile X& или const изменчивый X &.
12.8 [class.copy] / 18 Если определение класса явно не объявляет оператор присваивания копии, он объявляется неявно.
Нет, как только вы объявляете свой собственный конструктор копирования или оператор копирования (независимо от того, использует ли он канонический const
Несомненно) компилятор больше не сделает это за вас.
Но делать это по неконстантным ссылкам - это в значительной степени пример нарушения принципа наименьшего удивления. Все ожидают, что объекты const могут быть назначены и что правая часть не будет видоизменена. Первое не так уж и плохо, так как компилятор его поймает, а второе может привести к множеству трудно обнаруживаемых ошибок.
Если вы пытаетесь реализовать семантику перемещения и не можете использовать C++11, я бы предложил создать специальный метод перемещения и просто вообще не разрешать конструкцию "перемещения". Если вы можете использовать C++11, тогда используйте встроенные ссылки на rvalue.