C++: автоматически сгенерированный (по умолчанию) копировальный конструктор
Если я объявлю класс как, (без динамического выделения памяти, без указателя):
class A{
int a,b;
public:
A();
A(int,int);
A& operator=(const A);
};
Безопасно ли не объявлять конструктор копирования? Как выглядит конструктор копирования по умолчанию?
A& A::operator=(const A other)
{
a=other.a;
b=other.b;
return *this;
}
Даже если я не объявляю конструктор копирования, он будет вызываться по умолчанию, когда я вызываю operator=()
РЕДАКТИРОВАТЬ:
деструктор по умолчанию:
A::~A(){}
так что здесь не нужно
4 ответа
Правило таково: если вам нужно предоставить либо:
- Копировать конструктор или
- деструктор или
- оператор копирования
тогда вам, вероятно, нужно предоставить все три из них. Это правило известно как правило трех.
Можно ли не объявлять конструктор копирования?
Это безопасно.
Вы должны для вашего примера дела?
На самом деле, нет. Чтобы быть конкретным, правило трех управляет этим. Проверьте связанный вопрос для более подробной информации об этом.
Как выглядит конструктор копирования по умолчанию?
Я понял, что спрашивает, что делает конструктор копирования по умолчанию.
Это ответ в:
C++ 03 Standard 12.8 Копирование объектов класса:
Параграф 8:
Неявно определенный конструктор копирования для класса X выполняет пошаговое копирование своих подобъектов. Порядок копирования такой же, как порядок инициализации баз и элементов в определяемом пользователем конструкторе (см. 12.6.2). Каждый подобъект копируется способом, соответствующим его типу:
- если подобъект имеет тип класса, используется конструктор копирования для класса;
- если подобъект является массивом, каждый элемент копируется способом, соответствующим типу элемента;
- если подобъект имеет скалярный тип, используется встроенный оператор присваивания.
Субъекты виртуального базового класса должны быть скопированы неявно определенным конструктором копирования только один раз (см. 12.6.2).
Даже если я не объявляю конструктор копирования, при вызове будет вызываться конструктор по умолчанию
operator=()
Конструктор копирования вызывается только тогда, когда необходимо создать копию объекта класса. Это включает в себя копии объектов, созданных при передаче или возвращении из функций.
Ваш оператор присвоения копии передает объект A
по значению этот проход по значению достигается путем передачи копии объекта через конструктор копирования и, следовательно, вызова конструктора копирования.
Чтобы избежать копирования вам нужно пройти по ссылке:
A& A::operator=(const A& other)
Хорошо для чтения:
В чем разница между передачей по ссылке и передачей по значению?
Вы, кажется, путаете конструкторы копирования с операторами назначения копирования. Неявно сгенерированный конструктор копирования будет копировать-конструировать каждый из членов:
A::A( A const& source )
: a( source.a )
, b( source.b )
{}
Неявно сгенерированный оператор копирования-назначения будет копировать-присваивать каждому из членов:
A& A::operator =( A const& source )
{
a = source.a;
b = source.b;
return *this;
}
Оператор копирования-назначения, как вы определили его в своем вопросе, принимает A
по копии, поэтому будет вызван конструктор копирования для создания аргумента, переданного operator=
, Обратите внимание, что копия может быть аннулирована при определенных обстоятельствах.
Ваш класс обеспечивает operator=
, Согласно правилу трех (как говорит @AlokSave), вы должны также предоставить конструктор копирования и деструктор.
Вопрос в том, что если вы довольны предоставленным по умолчанию конструктором копирования, почему вас не устраивает заданный по умолчанию оператор присваивания копии? И если вы, просто не объявляйте operator=
и пусть компилятор сгенерирует все "правило трех" для вас.