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 C
merupakan 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 C
dideklarasikan 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{};
B
bukan 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 A
konstruktor default yang dilindungi.
Dalam C ++ 17, sebagai hasil dari P0017 , agregat diperluas untuk memungkinkan kelas dasar. B
adalah agregat dalam C ++ 17, yang berarti B{}
inisialisasi agregat yang harus menginisialisasi semua subobjek - termasuk A
subobjek. Tetapi karena A
konstruktor default dilindungi, kami tidak memiliki akses ke sana, jadi inisialisasi ini salah bentuk.
Dalam C ++ 20, karena B
konstruktor 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?