В чем разница между перегрузкой operator = и перегрузкой конструктора копирования? - PullRequest
9 голосов
/ 21 июня 2011

В чем разница между перегрузкой оператора = в классе и конструктором копирования ?

В каком контексте каждый из них называется?

Я имею в виду, если у меня есть следующее:

Person *p1 = new Person("Oscar", "Mederos");
Person *p2 = p1;

Какой из них используется? А потом, когда другой используется?

Изменить:
Просто чтобы немного уточнить:

Я уже знаю, что если мы явно вызовем конструктор копирования Person p1(p2), будет использован конструктор копирования. Я хотел знать, когда каждый из них используется, но вместо этого используется оператор =, как указал @Martin.

Ответы [ 3 ]

12 голосов
/ 21 июня 2011

В вашем случае ни один из них не используется, так как вы копируете указатель.

Person p1("Oscar", "Mdderos");
Person extra;

Конструктор копирования

Person P2(p1);      // A copy is made using the copy constructor
Person P3  = p2;    // Another form of copy construction.
                    // P3 is being-initialized and it uses copy construction here
                    // NOT the assignment operator

Назначение:

extra = P2;         // An already existing object (extra)
                    // is assigned to.

Стоит отметить, что оператор присваивания может быть записан в терминах конструктора копирования с использованием Copy and Swap idium:

class Person
{
    Person(std::string const& f, std::string const& s);
    Person(Person const& copy);

    // Note: Do not use reference here.
    //       Thus getting you an implicit copy (using the copy constructor)
    //       and thus you just need to the swap
    Person& operator=(Person copy)
    {
        copy.swap(*this);
        return *this;
    }

    void swap(Person& other) throws()
    {
          // Swap members of other and *this;
    }
};
5 голосов
/ 21 июня 2011

Конструктор копирования - это конструктор , он создает объект. В частности, конструктор копирования создает объект, который семантически идентичен другому, уже существующему объекту, из которого он создает «копию»:

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; Это синтаксический сахар, позволяющий вам писать естественно выглядящий код без ущерба для эффективности (или даже правильности, поскольку ваш класс может даже не быть конструируемым по умолчанию).

0 голосов
/ 26 сентября 2013

Конструктор копирования создает новый объект, используя содержимое объекта аргумента. перегруженный оператор присваивания присваивает содержимое существующего объекта другому существующему объект того же класса.

...