Pertanyaan Apa yang dilakukan kolon setelah nama konstruktor C ++? [duplikat]


Pertanyaan ini sudah memiliki jawaban di sini:

Apa yang dilakukan operator kolon (":") dalam konstruktor ini? Apakah itu setara dengan MyClass(m_classID = -1, m_userdata = 0);?

class MyClass {
public:

    MyClass() : m_classID(-1), m_userdata(0) { 
    }

    int m_classID;
    void *m_userdata;
};

76
2017-08-13 15:22


asal


Jawaban:


Ini adalah sebuah daftar inisialisasi, dan merupakan bagian dari implementasi konstruktor.

Tanda tangan konstruktor adalah:

MyClass();

Ini berarti bahwa konstruktor dapat dipanggil tanpa parameter. Ini membuatnya menjadi konstruktor default, yaitu, yang akan dipanggil secara default saat Anda menulis MyClass someObject;.

Bagian : m_classID(-1), m_userdata(0) disebut daftar inisialisasi. Ini adalah cara untuk menginisialisasi beberapa bidang objek Anda (semuanya, jika Anda mau) dengan nilai-nilai pilihan Anda, daripada membiarkannya tidak terdefinisi.

Setelah mengeksekusi daftar inisialisasi, badan konstruktor (yang kebetulan kosong dalam contoh Anda) dieksekusi. Di dalamnya Anda dapat melakukan lebih banyak tugas, tetapi setelah Anda memasukkannya, semua bidang telah diinisialisasi - baik ke acak, nilai yang tidak ditentukan, atau ke yang Anda pilih dalam daftar inisialisasi Anda. Ini berarti tugas yang Anda lakukan dalam badan konstruktor tidak akan menjadi inisialisasi, tetapi perubahan nilai.


82
2017-08-13 15:26



Ini adalah daftar inisialisasi.

Pada saat Anda masuk ke dalam tubuh konstruktor, semua bidang telah dibangun; jika mereka memiliki konstruktor default, yang sudah dipanggil. Sekarang, jika Anda menetapkan nilai kepada mereka di badan konstruktor, Anda memanggil operator penugasan salinan, yang dapat berarti melepaskan dan mendapatkan kembali sumber daya (misalnya memori) jika objek tersebut memiliki.

Jadi dalam kasus tipe primitif seperti int, tidak ada keuntungan dibandingkan dengan menugaskan mereka di dalam tubuh konstruktor. Dalam kasus objek yang memiliki konstruktor, itu adalah optimasi kinerja karena menghindari melalui dua inisialisasi objek, bukan satu.

Daftar inisialisasi diperlukan jika salah satu bidang adalah referensi karena referensi tidak boleh nol, bahkan tidak dalam waktu singkat antara konstruksi objek dan badan konstruktor. Berikut ini menimbulkan kesalahan C2758: 'MyClass :: member_': harus diinisialisasi dalam konstruktor base / member initializer list

class MyClass {
public :
    MyClass(std::string& arg) {
        member_ = arg;
    }
    std::string& member_;
};

Satu-satunya cara yang benar adalah:

class MyClass {
public :
    MyClass(std::string& arg) 
        : member_(arg) 
    {
    }
    std::string& member_;
};

40
2017-08-13 15:37



Ini menunjukkan awal dari daftar initialiser, yang untuk menginisialisasi variabel anggota objek Anda.

Mengenai: MyClass(m_classID = -1, m_userdata = 0);

Itu menyatakan konstruktor yang dapat mengambil argumen (jadi saya bisa membuat MyClass menggunakan MyClass m = MyClass(3, 4), yang akan menghasilkan m_classID menjadi 3, dan m_userdata menjadi 4). Jika saya tidak melewati argumen ke MyClass konstruktor, itu akan menghasilkan objek yang setara yang dibuat ke versi dengan daftar initialiser.


2
2017-08-13 15:25



Ini menandakan awal daftar penginisialisasi.

Juga tidak setara dengan MyClass (m_classId = -1, m_userData = 0). Ini mencoba mendefinisikan konstruktor dengan 2 parameter yang memiliki nilai default. Namun nilai-nilai tidak memiliki tipe dan seharusnya tidak dikompilasi sama sekali.


2
2017-08-13 15:27



Itu a daftar inisialisasi. Dalam contoh Anda, itu agak seperti ini (sesuatu seperti ini - tidak berarti itu setara dalam semua kasus):


class MyClass {

public:

    MyClass(){
         m_classID = -1;
         m_userdata = 0;
    }

    int m_classID;
    void *m_userdata;

};

1
2017-08-13 15:26



Itu disebut daftar inisialisasi anggota. Ini digunakan untuk memanggil konstruktor superclass, dan memberikan variabel anggota Anda sebagai nilai awal pada saat mereka dibuat.

Dalam hal ini, ini menginisialisasi m_classID ke -1 dan m_userData ke NULL.

Ini tidak cukup setara dengan menugaskan dalam tubuh konstruktor, karena yang terakhir pertama kali menciptakan variabel anggota, lalu menugaskan kepada mereka. Dengan inisialisasi, nilai awal diberikan pada saat penciptaan, jadi dalam kasus objek yang kompleks, itu bisa lebih efisien.


1
2017-08-13 15:27



Itu bukan operator. Ini adalah bagian dari sintaks untuk konstruktor.

Apa yang dikatakannya adalah bahwa mengikuti ini akan menjadi daftar variabel anggota dan nilai awal mereka.

Anggota Konstan harus diinisialisasi dengan cara ini. Non-konstanta dapat diinisialisasi di sini juga, asalkan dapat dilakukan dengan ekspresi tunggal. Jika butuh lebih banyak kode dari itu untuk menginisialisasi anggota, Anda harus memasukkan kode aktual di antara {} untuk melakukannya.

Banyak orang suka menempatkan hampir semua kode konstruktor mereka dalam daftar initilizer. Saya memiliki satu rekan kerja yang secara teratur menulis kelas dengan beberapa layar initilis, dan kemudian menempatkan "{}" untuk kode konstruktor.


1
2017-08-13 15:28



Ini adalah awal dari daftar initialiser yang menetapkan variabel anggota selama pembangunan objek. Contoh Anda "MyClass (m_classID = -1, m_userdata = 0);" tidak mungkin karena Anda belum mendefinisikan konstruktor yang benar dan Anda tidak akan dapat mengakses variabel anggota dalam daftar parameter ... Anda bisa memiliki sesuatu seperti:

MyClass( int classId = -1, void* userData = 0 ) : m_classID(classId), m_userdata(userData) {}

Daftar penginisialisasi dianggap lebih baik daripada:

MyClass( int classId = -1, void* userData = 0 ) {
    m_classID = classId;
    m_userdata = userData;
}

Google untuk info lebih lanjut.


1
2017-08-13 15:29



Dalam hal ini: Ya, ist adalah setara karena hanya tipe primitif yang bersangkutan.

Jika anggota adalah kelas (struct) maka Anda harus memilih daftar inisialisasi. Ini karena jika tidak objek-objeknya dibangun secara default dan kemudian ditugaskan.


0
2017-08-13 15:25