Apa perbedaan antara operator tugas dan konstruktor salinan?


105

Saya tidak mengerti perbedaan antara konstruktor tugas dan konstruktor salinan di C ++. Seperti ini:

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

// The copy constructor
A a = b;

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

// Is it right?

Saya ingin tahu bagaimana mengalokasikan memori konstruktor tugas dan menyalin konstruktor?


2
Apakah Anda memiliki buku C ++ yang bagus ?
sbi

Jawaban:


160

Sebuah copy constructor digunakan untuk menginisialisasi sebelumnya diinisiasi objek dari data beberapa objek lain.

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

Sebagai contoh:

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

Sebuah operator penugasan digunakan untuk mengganti data dari sebelumnya diinisialisasi objek dengan data beberapa objek lain.

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

Sebagai contoh:

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

Anda dapat mengganti konstruksi salinan dengan konstruksi default ditambah tugas, tetapi itu akan kurang efisien.

(Sebagai catatan tambahan: Implementasi saya di atas persis seperti yang diberikan compiler kepada Anda secara gratis, jadi tidak masuk akal untuk mengimplementasikannya secara manual. Jika Anda memiliki salah satu dari keduanya, kemungkinan Anda mengelola beberapa resource secara manual. Dalam hal ini, sesuai The Rule of Three , Anda kemungkinan besar juga akan membutuhkan yang lain plus destruktor.)


4
Sekadar catatan: Saat ini (C ++ 11 dan seterusnya), mereka dapat secara eksplisit menggunakan default =default;.
Deduplicator

2
@Deduplicator Penting juga untuk menyebutkan bahwa, ketika mengikuti klasifikasi yang membutuhkan konstruktor sepele, Anda harus = default mereka di mana ctor default diperlukan: cukup mengimplementasikan tubuh kosong sendiri masih dihitung sebagai ctor yang ditentukan pengguna dan dengan demikian (pada tingkat Standar ) tidak sepele dan mendiskualifikasi tipe dari klasifikasi yang membutuhkan ctor sepele.
underscore_d

@sbi Dapatkah saya mengatakan bahwa dalam kasus copy konstruktor tidak digunakan dan sebaliknya operator penugasan digunakan, objek dibuat terlebih dahulu dengan memanggil konstruktor baik dengan argumen atau tanpa argumen dan kemudian operator penugasan digunakan dan nilai baru ditetapkan berdasarkan RHS. Jika konstruktor salinan digunakan, konstruktor yang sama akan dipanggil, tetapi nilai yang digunakan untuk inisialisasi berasal dari objek lain.
Rajesh

@Rajesh: Saya bingung tentang apa yang Anda tanyakan, dan perasaan saya itu karena Anda juga bingung. :)Maukah Anda mencoba menjelaskan lagi apa yang Anda bicarakan?
sbi

1
@ CătălinaSîrbu: Anda bisa. Mereka adalah dua fungsi independen.
sbi

41

Perbedaan antara copy constructor dan operator penugasan menyebabkan banyak kebingungan bagi programmer baru, tetapi sebenarnya tidak terlalu sulit. Meringkas:

  • Jika objek baru harus dibuat sebelum penyalinan dapat terjadi, konstruktor salinan digunakan.
  • Jika objek baru tidak harus dibuat sebelum penyalinan dapat terjadi, operator penugasan digunakan.

Contoh untuk operator penugasan:

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

Contoh untuk copy konstruktor:

Base obj1(5);
Base obj2 = obj1; //calls copy constructor

Apakah adil untuk mengatakan bahwa operator penugasan secara efektif menggabungkan penghancuran objek lama dengan pembuatan yang baru, tetapi dengan ketentuan bahwa (1) jika salah satu langkah dalam penghancuran objek lama akan dibatalkan oleh salah satu langkah dalam pembangunan yang baru, kedua langkah tersebut dapat dihilangkan; (2) operator penugasan tidak boleh melakukan hal-hal buruk jika sebuah objek ditugaskan ke dirinya sendiri.
supercat

mengapa melakukan vector <A> v3dan kemudian v3 = v2 (di mana v2yang sebelumnya dideklarasikan dan mengandung elemen vector<A>) memanggil Akonstruktor copy eksplisit saya, bukan operator=? Saya mengharapkan operator=untuk dipanggil alih-alih copy constructorkarena v3objek saya telah diumumkan pada saat saya melakukan tugas
Cătălina Sîrbu

19

Yang pertama adalah inisialisasi salinan, yang kedua hanya tugas. Tidak ada yang namanya konstruktor tugas.

A aa=bb;

menggunakan konstruktor salinan yang dihasilkan kompilator.

A cc;
cc=aa;

menggunakan konstruktor default untuk membuat cc, lalu * operator penugasan ** ( operator =) pada objek yang sudah ada.

Saya ingin tahu bagaimana mengalokasikan memori konstruktor tugas dan menyalin konstruktor?

IDK yang Anda maksud dengan mengalokasikan memori dalam kasus ini, tetapi jika Anda ingin melihat apa yang terjadi, Anda dapat:

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;}
};

Saya juga menyarankan Anda untuk melihat:

Mengapa konstruktor salinan disebut sebagai ganti konstruktor konversi?

Apa The Rule of Three?


5

Dengan kata sederhana,

Salin konstruktor dipanggil ketika objek baru dibuat dari objek yang sudah ada, sebagai salinan dari objek yang sudah ada. Dan operator penugasan dipanggil ketika objek yang sudah diinisialisasi diberi nilai baru dari objek lain yang sudah ada.

Contoh-

t2 = t1;  // calls assignment operator, same as "t2.operator=(t1);"
Test t3 = t1;  // calls copy constructor, same as "Test t3(t1);"

4

Apa yang dikatakan @Luchian Grigore Said diimplementasikan seperti ini

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
}

KELUARAN


konstruktor default


salin konstruktor


konstruktor default


operator tugas



4

perbedaan antara konstruktor salinan dan konstruktor tugas adalah:

  1. Dalam kasus konstruktor salinan itu membuat objek baru. (<classname> <o1>=<o2> )
  2. Dalam kasus konstruktor tugas itu tidak akan membuat objek apa pun berarti itu berlaku pada objek yang sudah dibuat ( <o1>=<o2>).

Dan fungsi dasar di keduanya sama, mereka akan menyalin data dari o2 ke o1 anggota-demi-anggota.


2

Saya ingin menambahkan satu hal lagi tentang topik ini. "Fungsi operator dari operator penugasan harus ditulis hanya sebagai fungsi anggota kelas." Kita tidak bisa menjadikannya sebagai fungsi teman tidak seperti operator biner atau unary lainnya.


1

Sesuatu untuk ditambahkan tentang konstruktor salinan:

  • Saat mengirimkan objek berdasarkan nilai, itu akan menggunakan konstruktor salinan

  • Ketika sebuah objek dikembalikan dari fungsi dengan nilai, itu akan menggunakan konstruktor salinan

  • Saat menginisialisasi objek menggunakan nilai-nilai objek lain (seperti contoh yang Anda berikan).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.