Pentingnya Inisialisasi Tanpa Konstruktor
(consteval.ca)Saya tidak punya konstruktor dan harus diinisialisasi
-
Pendahuluan
- Saat pertama kali belajar C++, kita mempelajari kapan kompiler menyediakan konstruktor bawaan.
- Ini menimbulkan pertanyaan tentang risiko objek yang mungkin tidak terinisialisasi dalam situasi tertentu.
-
Inisialisasi bawaan dan inisialisasi nilai
T t;melakukan inisialisasi bawaan.- Jika
Tadalah tipe kelas dan memiliki konstruktor bawaan, maka konstruktor itu dijalankan. - Jika
Tadalah tipe array, maka setiap elemennya diinisialisasi secara bawaan. - Jika tidak, tidak ada yang dilakukan.
- Jika
T t{};melakukan inisialisasi nilai.- Jika
Tadalah tipe kelas, maka dilakukan inisialisasi bawaan bila tidak ada konstruktor bawaan atau bila konstruktor bawaan disediakan pengguna atau dihapus. - Jika tidak, objek diinisialisasi ke 0 lalu dilakukan inisialisasi bawaan.
- Jika
Tadalah tipe array, maka setiap elemennya diinisialisasi sebagai nilai. - Jika tidak, objek diinisialisasi ke 0.
- Jika
-
Konstruktor bawaan
- Jika tidak mendeklarasikan konstruktor bawaan, kompiler akan mendeklarasikannya secara implisit.
- Konstruktor bawaan yang dideklarasikan secara implisit memiliki body kosong dan daftar inisialisasi anggota yang kosong.
- Contoh:
struct T { int x; T() = default; }; T t{}; std::cout << t.x << std::endl; // hasil output adalah 0
-
Konstruktor bawaan yang didefinisikan secara implisit
- Jika konstruktor bawaan dideklarasikan secara implisit atau dideklarasikan secara eksplisit sebagai default, kompiler akan menyediakan konstruktor bawaan yang didefinisikan secara implisit.
- Contoh:
struct T { T(); }; T::T() = default; T t{}; std::cout << t.x << std::endl; // hasil output adalah nilai sampah
-
Kasus ketika konstruktor bawaan tidak bisa disediakan
- Jika
Tmemiliki anggota referensi non-statis - Jika
Tmemiliki anggota non-statis atau kelas dasar non-abstrak yang tidak bisa dibangun secara bawaan atau tidak bisa dihancurkan - Jika
Tmemiliki anggota non-statisconsttanpa inisialisator anggota bawaan
- Jika
-
Inisialisasi yang benar
T t{};melakukan inisialisasi daftar.- Inisialisasi daftar dibagi menjadi inisialisasi daftar langsung dan inisialisasi daftar salin.
- Contoh:
struct S { int a; float b; char c; }; S s{3, 4.0f, 'S'}; // tidak ada pemanggilan konstruktor
-
Inisialisasi daftar dan inisialisasi agregat
- Inisialisasi agregat adalah bentuk khusus dari inisialisasi daftar, yang melakukan inisialisasi salin pada setiap elemen kelas atau array dengan elemen yang sesuai dari daftar inisialisasi.
- Contoh:
struct A { const int x; }; A a{}; // a.x diinisialisasi ke 0
-
Inisialisasi dengan tanda kurung
- Inisialisasi dengan tanda kurung melakukan inisialisasi langsung non-daftar.
- Contoh:
struct T { const int& r; }; T t(42); // t.r adalah referensi yang menunjuk ke 42
-
Ringkasan
- Aturan inisialisasi memang rumit, tetapi sebagian besar masalah bisa dihindari dengan menulis konstruktor secara langsung.
- Sebaiknya jangan menyerahkan semuanya pada kompiler; menulis konstruktor sendiri adalah pilihan yang lebih baik.
Opini GN⁺
- Artikel ini menjelaskan dengan baik kompleksitas aturan inisialisasi di C++.
- Memahami aturan inisialisasi C++ itu penting karena sangat memengaruhi stabilitas dan performa kode.
- Menulis konstruktor secara langsung adalah cara terbaik untuk menghindari masalah inisialisasi.
- Bahasa lain dengan fungsi serupa adalah Rust, dan Rust memiliki aturan inisialisasi yang lebih jelas.
- Saat mengadopsi teknologi baru, penting untuk memahami dan menggunakan detail seperti aturan inisialisasi dengan baik.
1 komentar
Komentar Hacker News
Hasil inisialisasi
takan menjadi 0tmengalami value-initialization, dan karenaTtidak memiliki user-defined default constructor, objek di-zero-initialize lalu default constructor dipanggilDefault constructor melakukan default-initialization pada anggota, dan ini berbeda dari value-initialization
GCC tampaknya setuju dengan hal ini
Penulis melewatkan bahwa sebenarnya ia sedang melakukan value-initialization pada
xDetail aturannya rumit dan kadang ada bagian yang tidak masuk akal
Membuat default-initialization menjadi eksplisit akan menjadi perbaikan besar
std::array<int, 100> = void;akan lebih baikPenghubung antara list-initialization dan aggregate initialization adalah bahwa ketika list-initialization dilakukan pada aggregate, maka aggregate initialization yang dijalankan
Kasus satu elemen bekerja berbeda dari dua elemen atau lebih
Anda bisa menulis constructor sendiri dan menginisialisasi tuple atau array yang hanya diberi satu elemen
Saat initialization list C++11 pertama kali muncul, saya menemukannya dan menganggapnya gila
Menyebut "I Have No Mouth, and I Must Scream" (1967)
Menggunakan sintaks
T::T() = default;Orang berharap hasil output akan menjadi 0, tetapi kenyataannya akan keluar nilai sampah
Memungkinkan konsumen library mengubah perilaku library
Jika ingin lebih banyak kerumitan C++, C++ FQA direkomendasikan
Tema blog terinspirasi dari komputer era DEC, tetapi tetap rapi dan minimalis
Membaca ini membuat kepala pusing
Go dan Rust tidak punya constructor khusus, sehingga banyak hal jadi lebih sederhana
Penasaran apakah ada alat C++ yang menampilkan semua perilaku implisit
Memberikan informasi yang salah tentang class
Klaim bahwa "T t;" berarti "tidak melakukan apa-apa" itu salah
T t;gagalAda panel depan DEC di header blog