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

107

Я не понимаю разницы между конструктором присваивания и конструктором копирования в C ++. Это так:

class A {
public:
    A() {
        cout << "A::A()" << endl;
    }
};

// The copy constructor
A a = b;

// The assignment constructor
A c;
c = a;

// Is it right?

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

alan.chen
источник
2
У вас есть хорошая книга по C ++ ?
sbi
связанные FAQ
fredoverflow

Ответы:

161

Конструктор копирования используется для инициализации ранее неинициализированный объект из данных какого - то другого объекта.

A(const A& rhs) : data_(rhs.data_) {}

Например:

A aa;
A a = aa;  //copy constructor

Оператор присваивания используется для замены данных в ранее инициализирован объект с данными какого - то другого объекта.

A& operator=(const A& rhs) {data_ = rhs.data_; return *this;}

Например:

A aa;
A a;
a = aa;  // assignment operator

Вы можете заменить построение копии построением по умолчанию плюс присваивание, но это будет менее эффективно.

(В качестве примечания: мои реализации выше - это именно те, которые компилятор предоставляет вам бесплатно, поэтому не имеет смысла реализовывать их вручную. Если у вас есть один из этих двух, вероятно, вы вручную управляете каким-то ресурсом. В этом случае, согласно Правилу трех , вам, скорее всего, также понадобится второй плюс деструктор.)

SBI
источник
4
Просто примечание: в настоящее время (начиная с C ++ 11) для них можно явно указать значения по умолчанию =default;.
Дедупликатор
2
@Deduplicator Также важно упомянуть, что при соблюдении классификаций, требующих тривиальных конструкторов, вы должны = default их использовать там, где требуется ctor по умолчанию: простая реализация пустого тела самостоятельно по-прежнему считается определяемым пользователем ctor и, таким образом (на стандартном уровне ) нетривиален и исключает тип из классификаций, требующих тривиального ctor.
underscore_d
@sbi Могу ли я сказать, что в случае, если конструктор копирования не используется, а вместо него используется оператор присваивания, сначала создается объект, вызывая конструктор с аргументами или без аргументов, а затем используется оператор присваивания и новые значения присваиваются на основе RHS. В случае использования конструктора копирования будет вызван все тот же конструктор, но значения, используемые для инициализации, взяты из другого объекта.
Раджеш
@Rajesh: Я не понимаю, о чем вы спрашиваете, и мне кажется, это потому, что вы тоже в замешательстве. :)Попробуете еще раз объяснить, о чем говорите?
sbi
1
@ CătălinaSîrbu: Вы могли бы. Это две независимые функции.
SBI
42

Разница между конструктором копирования и оператором присваивания вызывает большое недоумение у начинающих программистов, но на самом деле это не так уж и сложно. Резюмируя:

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

Пример оператора присваивания:

Base obj1(5); //calls Base class constructor
Base obj2; //calls Base class default constructor
obj2 = obj1; //calls assignment operator

Пример конструктора копирования:

Base obj1(5);
Base obj2 = obj1; //calls copy constructor
Арун
источник
Было бы справедливо сказать, что оператор присваивания эффективно сочетает уничтожение старого объекта с созданием нового, но с оговорками, что (1) если один из шагов по уничтожению старого объекта будет отменен один из этапов строительства нового, оба этапа могут быть опущены; (2) операторы присваивания не должны делать ничего плохого, если объект присваивается сам себе.
supercat
зачем делать, vector <A> v3а затем v3 = v2 (где v2ранее объявленные и содержащие элементы vector<A>) вызывает мой явный Aконструктор копирования вместо operator=? Я ожидал , что operator=будет называться вместо copy constructorпотому , что мой v3объект уже был объявлен в то время , когда я сделал назначение
Catalina Sîrbu
19

Первый - инициализация копии, второй - просто присваивание. Конструктора присваивания не существует.

A aa=bb;

использует созданный компилятором конструктор копирования.

A cc;
cc=aa;

для построения использует конструктор по умолчанию cc, а затем * оператор присваивания ** ( operator =) для уже существующего объекта.

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

IDK, что вы имеете в виду под выделением памяти в этом случае, но если вы хотите увидеть, что происходит, вы можете:

class A
{
public :
    A(){ cout<<"default constructor"<<endl;};
    A(const A& other){ cout<<"copy constructor"<<endl;};
    A& operator = (const A& other){cout <<"assignment operator"<<endl;}
};

Также рекомендую вам взглянуть на:

Почему вызывается конструктор копирования вместо конструктора преобразования?

Что такое правило трех?

Лучиан Григоре
источник
5

Проще говоря,

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

Пример-

t2 = t1;  // calls assignment operator, same as "t2.operator=(t1);"
Test t3 = t1;  // calls copy constructor, same as "Test t3(t1);"
Сатиш
источник
4

Что @Luchian Grigore Said реализовано вот так

class A
{
public :
    int a;
    A(){ cout<<"default constructor"<<endl;};
    A(const A& other){ cout<<"copy constructor"<<endl;};
    A& operator = (const A& other){cout <<"assignment operator"<<endl;}
};

void main()
{
    A sampleObj; //Calls default constructor
    sampleObj.a = 10;

    A copyConsObj  = sampleObj; //Initializing calls copy constructor

    A assignOpObj; //Calls default constrcutor
    assignOpObj = sampleObj; //Object Created before so it calls assignment operator
}

ВЫВОД


конструктор по умолчанию


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


конструктор по умолчанию


оператор присваивания


Мак
источник
4

разница между конструктором копирования и конструктором присваивания:

  1. В случае конструктора копирования он создает новый объект. ( <classname> <o1>=<o2>)
  2. В случае конструктора присваивания он не будет создавать никаких объектов, это означает, что он применяется к уже созданным объектам ( <o1>=<o2>).

И основные функции в обоих одинаковы, они будут копировать данные из o2 в o1 поэтапно.

Нитеш Кумар
источник
2

Хочу добавить еще один момент по этой теме. «Операторная функция оператора присваивания должна быть написана только как функция-член класса». Мы не можем сделать это функцией друга, в отличие от других бинарных или унарных операторов.

MD БЕЛАЛ РАШИД
источник
1

Кое-что добавить о конструкторе копирования:

  • При передаче объекта по значению он будет использовать конструктор копирования

  • Когда объект возвращается из функции по значению, он будет использовать конструктор копирования

  • При инициализации объекта с использованием значений другого объекта (как в приведенном вами примере).

Франк Шен
источник