Angew ini dan jaggedSpire ini jawaban yang sangat baik dan berlaku untukc ++ 11. Danc ++ 14. Danc ++ 17.
Namun, dalam c ++ 20, banyak hal berubah sedikit dan contoh di OP tidak akan lagi dikompilasi:
class C {
C() = default;
};
C p;
auto q = C();
C r{};
auto s = C{};
Seperti yang ditunjukkan oleh dua jawaban, alasan kedua deklarasi terakhir berfungsi adalah karena Cmerupakan agregat dan ini adalah inisialisasi agregat. Namun, sebagai hasil dari P1008 (menggunakan contoh motivasi yang tidak terlalu berbeda dari OP), definisi agregat berubah dalam C ++ 20 menjadi, dari [dcl.init.aggr] / 1 :
Agregat adalah larik atau kelas ([class]) dengan
- tidak ada yang diumumkan pengguna konstruktor yang atau diwariskan pengguna ([class.ctor]),
- tidak ada anggota data non-statis langsung pribadi atau dilindungi ([class.access]),
- tidak ada fungsi virtual ([class.virtual]), dan
- tidak ada kelas dasar virtual, privat, atau dilindungi ([class.mi]).
Penekanan milikku. Sekarang persyaratannya adalah tidak ada konstruktor yang dideklarasikan pengguna , sedangkan dulu (karena kedua pengguna mengutip jawaban mereka dan dapat dilihat secara historis untuk C ++ 11 , C ++ 14 , dan C ++ 17 ) tidak ada konstruktor yang disediakan pengguna . Konstruktor default untuk Cdideklarasikan oleh pengguna, tetapi tidak disediakan pengguna, dan karenanya berhenti menjadi agregat di C ++ 20.
Berikut adalah contoh ilustrasi lain dari perubahan agregat:
class A { protected: A() { }; };
struct B : A { B() = default; };
auto x = B{};
Bbukan agregat di C ++ 11 atau C ++ 14 karena memiliki kelas dasar. Akibatnya, B{}cukup panggil konstruktor default (dideklarasikan pengguna tetapi tidak disediakan pengguna), yang memiliki akses ke Akonstruktor default yang dilindungi.
Dalam C ++ 17, sebagai hasil dari P0017 , agregat diperluas untuk memungkinkan kelas dasar. Badalah agregat dalam C ++ 17, yang berarti B{}inisialisasi agregat yang harus menginisialisasi semua subobjek - termasuk Asubobjek. Tetapi karena Akonstruktor default dilindungi, kami tidak memiliki akses ke sana, jadi inisialisasi ini salah bentuk.
Dalam C ++ 20, karena Bkonstruktor yang dideklarasikan oleh pengguna, ia kembali berhenti menjadi agregat, jadi B{}kembali ke pemanggilan konstruktor default dan ini adalah inisialisasi yang dibentuk dengan baik.
C c{};inisialisasi agregat jadi tidak ada konstruktor yang dipanggil?