Конструктор копирования - это конструктор , он создает объект. В частности, конструктор копирования создает объект, который семантически идентичен другому, уже существующему объекту, из которого он создает «копию»:
Person newperson(oldperson); // newperson is a "copy" of oldperson
Оператор присваивания вовсе не конструктор, а функция обычного члена, которая может быть вызвана только для существующего объекта. Его назначение - присвоить вашему объекту семантику другого объекта, чтобы после присвоения оба семантически были идентичны. Обычно вы не «перегружаете» оператор присваивания, вы просто его определяете.
Person p; // construct new person
/* dum-dee-doo */
p = otherperson; // assign to p the meaning of otherperson, overwriting everything it was before
// invokes p.operator=(otherperson)
Обратите внимание, что если имеет смысл сравнивать с объектами (с ==
), то и конструкция копирования, и присвоение должны вести себя так, чтобы впоследствии мы имели равенство:
Person p1(p2);
assert(p1 == p2);
p1 = p3;
assert(p1 == p3);
Вы не обязаны это гарантировать, но пользователи вашего класса обычно принимают такое поведение. Фактически, компилятор предполагает, что Person p1; Person p2(p1);
влечет за собой p1 == p2;
.
И, наконец, как последнее замечание и, как сказано в другом месте, обратите внимание, что Person p = p2;
буквально означает Person p(p2)
(копирование), а никогда Person p; p = p2;
Это синтаксический сахар, позволяющий вам писать естественно выглядящий код без ущерба для эффективности (или даже правильности, поскольку ваш класс может даже не быть конструируемым по умолчанию).