Bisakah seseorang menjelaskan mengapa pointer tidak diinisialisasi NULL
?
Contoh:
void test(){
char *buf;
if (!buf)
// whatever
}
Program tidak akan masuk ke dalam jika karena buf
bukan null.
Saya ingin tahu mengapa, dalam hal apa kita memerlukan variabel dengan tempat sampah aktif, khususnya penunjuk yang menangani sampah di memori?
c++
memory
pointers
initialization
Jonathan
sumber
sumber
Jawaban:
Kita semua menyadari bahwa pointer (dan jenis POD lainnya) harus diinisialisasi.
Pertanyaannya kemudian menjadi 'siapa yang harus menginisialisasi mereka'.
Pada dasarnya ada dua metode:
Mari kita asumsikan bahwa kompilator menginisialisasi variabel apa pun yang tidak diinisialisasi secara eksplisit oleh pengembang. Kemudian kami mengalami situasi di mana menginisialisasi variabel tidak sepele dan alasan pengembang tidak melakukannya pada titik deklarasi adalah dia perlu melakukan beberapa operasi dan kemudian menetapkan.
Jadi sekarang kita memiliki situasi dimana kompilator telah menambahkan instruksi tambahan ke kode yang menginisialisasi variabel ke NULL kemudian kode pengembang ditambahkan untuk melakukan inisialisasi yang benar. Atau dalam kondisi lain variabel tersebut berpotensi tidak pernah digunakan. Banyak pengembang C ++ akan menjerit di bawah kedua kondisi dengan mengorbankan instruksi tambahan itu.
Ini bukan hanya tentang waktu. Tapi juga ruang. Ada banyak lingkungan di mana kedua sumber daya memiliki harga premium dan pengembang juga tidak ingin menyerah.
TAPI : Anda dapat mensimulasikan efek dari memaksa inisialisasi. Sebagian besar kompiler akan memperingatkan Anda tentang variabel yang tidak diinisialisasi. Jadi saya selalu mengubah level peringatan saya ke level tertinggi. Kemudian beri tahu kompilator untuk memperlakukan semua peringatan sebagai kesalahan. Dalam kondisi ini, sebagian besar kompiler akan menghasilkan kesalahan untuk variabel yang tidak diinisialisasi tetapi digunakan dan dengan demikian akan mencegah pembuatan kode.
sumber
Mengutip Bjarne Stroustrup di TC ++ PL (Edisi Khusus p. 22):
sumber
D
. Jika Anda tidak ingin inisialisasi, gunakan sintaks inifloat f = void;
atauint* ptr = void;
. Sekarang ini diinisialisasi secara default tetapi jika Anda benar-benar perlu, Anda dapat menghentikan kompilator untuk melakukannya.Karena inisialisasi membutuhkan waktu. Dan di C ++, hal pertama yang harus Anda lakukan dengan variabel apa pun adalah menginisialisasinya secara eksplisit:
atau:
atau:
sumber
Karena salah satu semboyan dari C ++ adalah:
Anda tidak membayar untuk apa yang tidak Anda gunakan
Untuk alasan ini,
operator[]
darivector
kelas tidak memeriksa apakah indeks di luar batas, misalnya.sumber
Untuk alasan sejarah, terutama karena ini adalah bagaimana hal itu dilakukan di C. Mengapa dilakukan seperti itu di C, adalah pertanyaan lain, tapi saya pikir prinsip overhead nol terlibat entah bagaimana dalam keputusan desain ini.
sumber
Selain itu, kami memiliki peringatan ketika Anda meledakkannya: "mungkin digunakan sebelum diberi nilai" atau verbage serupa tergantung pada kompiler Anda.
Anda melakukan kompilasi dengan peringatan, bukan?
sumber
Hanya ada sedikit situasi di mana masuk akal untuk variabel tidak diinisialisasi, dan inisialisasi default memiliki biaya yang kecil, jadi mengapa melakukannya?
C ++ bukan C89. Sial, bahkan C bukanlah C89. Anda dapat mencampur deklarasi dan kode, jadi Anda harus menunda deklarasi sampai Anda memiliki nilai yang sesuai untuk diinisialisasi.
sumber
Pointer hanyalah tipe lain. Jika Anda membuat
int
,char
atau jenis POD lainnya, itu tidak diinisialisasi ke nol, jadi mengapa harus ada pointer? Ini bisa dianggap overhead yang tidak perlu bagi seseorang yang menulis program seperti ini.Jika Anda tahu Anda akan memulainya, mengapa program harus mengeluarkan biaya saat Anda pertama kali membuat
pBuf
di bagian atas metode? Ini adalah prinsip overhead nol.sumber
Jika Anda menginginkan pointer yang selalu diinisialisasi ke NULL, Anda dapat menggunakan template C ++ untuk meniru fungsionalitas itu:
sumber
Foo *a
, Anda menggunakanInitializedPointer<Foo> a
- Latihan akademis murni karenaFoo *a=0
kurang mengetik. Namun kode di atas sangat berguna dari sudut pandang pendidikan. Dengan sedikit modifikasi (ke "placeholding" ctor / dtor dan operasi penugasan), itu dapat dengan mudah diperluas ke berbagai jenis smart pointer termasuk scoped-pointers (yang bebas pada destruktor) dan referensi-counted-pointer dengan menambahkan inc / dec operasi ketika m_pPointer diatur atau dihapus.Perhatikan bahwa data statis diinisialisasi ke 0 (kecuali Anda mengatakan sebaliknya).
Dan ya, Anda harus selalu mendeklarasikan variabel Anda selambat mungkin dan dengan nilai awal. Kode seperti
harus membunyikan bel alarm saat Anda membacanya. Saya tidak tahu apakah ada serat yang dapat dibujuk untuk mempermasalahkannya karena 100% legal.
sumber
Alasan lain yang mungkin mengapa, adalah bahwa pada penunjuk waktu tautan diberi alamat, tetapi pengalamatan tidak langsung / de-referensi penunjuk adalah tanggung jawab programmer. Biasanya, compiler tidak peduli, tetapi beban diteruskan ke programmer untuk mengelola pointer dan untuk memastikan tidak ada kebocoran memori yang terjadi.
Sungguh, singkatnya, mereka diinisialisasi dalam arti bahwa pada saat link, variabel pointer diberi alamat. Dalam kode contoh Anda di atas, yang dijamin akan crash atau menghasilkan SIGSEGV.
Demi kewarasan, selalu inisialisasi pointer ke NULL, dengan cara itu jika ada upaya untuk dereferensi tanpa
malloc
ataunew
akan memberi petunjuk kepada programmer tentang alasan mengapa program berperilaku salah.Semoga ini membantu dan masuk akal,
sumber
Nah, jika C ++ melakukan inisialisasi pointer, maka orang-orang C yang mengeluh "C ++ lebih lambat dari C" akan memiliki sesuatu yang nyata untuk dipegang;)
sumber
C ++ berasal dari latar belakang C - dan ada beberapa alasan yang muncul kembali dari ini:
C, bahkan lebih dari C ++ adalah pengganti bahasa assembly. Ia tidak melakukan apa pun yang tidak Anda perintahkan. Oleh karena itu: Jika Anda ingin membatalkannya - lakukanlah!
Juga, jika Anda membatalkan sesuatu dalam bahasa bare-metal seperti C secara otomatis pertanyaan konsistensi muncul: Jika Anda malloc sesuatu - haruskah itu secara otomatis menjadi nol? Bagaimana dengan struct yang dibuat di stack? haruskah semua byte menjadi nol? Bagaimana dengan variabel global? bagaimana dengan pernyataan seperti "(* 0x18);" bukankah itu berarti bahwa posisi memori 0x18 harus menjadi nol?
sumber
calloc()
.Apa petunjuk yang Anda bicarakan ini?
Untuk keamanan pengecualian, selalu menggunakan
auto_ptr
,shared_ptr
,weak_ptr
dan varian mereka yang lain.Ciri khas kode yang baik adalah yang tidak menyertakan satu panggilan pun
delete
.sumber
auto_ptr
dan gantikanunique_ptr
.Oh Boy. Jawaban sebenarnya adalah mudah untuk menghilangkan memori, yang merupakan inisialisasi dasar untuk, katakanlah sebuah pointer. Yang juga tidak ada hubungannya dengan menginisialisasi objek itu sendiri.
Mempertimbangkan peringatan yang diberikan sebagian besar kompiler pada level tertinggi, saya tidak dapat membayangkan pemrograman pada level tertinggi dan memperlakukannya sebagai kesalahan. Sejak menyalakannya tidak pernah menyelamatkan saya bahkan satu bug dalam jumlah besar kode yang dihasilkan, saya tidak dapat merekomendasikan ini.
sumber
NULL
, menginisialisasi untuk yang hanya sebanyak kesalahan.