Mempertimbangkan
int main()
{
auto a = new int[0];
delete[] a; // So there's no memory leak
}
Di antara inisialisasi dan penghapusan salinan, apakah Anda diizinkan membaca pointer di a + 1
?
Selanjutnya, apakah bahasa mengizinkan compiler untuk set a
ke nullptr
?
c++
language-lawyer
Batsyeba
sumber
sumber
a
dengan pasti (Anda tentu tidak bisa men-decere- nya).a + 1
", apakah kode berikut iniauto b = a + 1;
perilaku tidak terdefinisi? (Aku rasa ini).0
sebenarnya adalah hasil dari ekspresi yang Anda tidak akan tahu sampai runtime. Karenanew int[0]
aman, itu bisa menyelamatkan Anda khawatir tentang beberapa kasus percabangan / khusus. Bayangkan jika saya menginisialisasistd::vector
denganstd::vector<int> v(0);
.Jawaban:
Berdasarkan [basic.compound.3] , nilai yang disimpan
a
harus salah satu dari yang berikut:int
)Kita dapat mengesampingkan kemungkinan pertama karena tidak ada objek bertipe
int
dibangun. Kemungkinan ketiga dikesampingkan karena C ++ membutuhkan pointer non-null untuk dikembalikan (lihat [basic.stc.dynamic.allocation.2] ). Jadi kita dibiarkan dengan dua kemungkinan: sebuah pointer melewati ujung suatu objek atau sebuah pointer yang tidak valid.Saya akan cenderung untuk melihat
a
sebagai pointer masa lalu-akhir, tetapi saya tidak memiliki referensi yang memiliki reputasi untuk menetapkan itu. (Meskipun demikian, ada implikasi yang kuat dari ini di [basic.stc] , melihat bagaimana Anda dapatdelete
pointer ini.) Jadi saya akan menghibur kedua kemungkinan dalam jawaban ini.Perilaku tidak terdefinisi, seperti yang ditentukan oleh [expr.add.4] , terlepas dari kemungkinan yang dari atas berlaku.
Jika
a
adalah pointer masa lalu, maka dianggap menunjuk ke elemen hipotetis pada indeks0
array tanpa elemen. Menambahkan integerj
untuka
didefinisikan hanya ketika0≤0+j≤n
, di manan
adalah ukuran array. Dalam kasus kami,n
adalah nol, sehingga jumlahnyaa+j
didefinisikan hanya ketikaj
adalah0
. Secara khusus, menambahkan1
tidak ditentukan.Jika
a
tidak valid, maka kami dengan jelas jatuh ke dalam "Kalau tidak, perilaku tidak terdefinisi." (Tidak mengherankan, case yang didefinisikan hanya mencakup nilai pointer yang valid.)Tidak. Dari [basic.stc.dynamic.allocation.2] yang disebutkan di atas : "Jika permintaan berhasil, nilai yang dikembalikan oleh fungsi alokasi yang dapat diganti adalah nilai penunjuk yang bukan nol" . Ada juga catatan kaki yang menyebutkan bahwa C ++ (tetapi bukan C) membutuhkan pointer non-null sebagai respons terhadap permintaan nol.
sumber
Per diskusi reflektor CWG baru-baru ini sebagai hasil dari masalah editorial 3178 ,
new int[0]
menghasilkan apa yang saat ini disebut sebagai nilai penunjuk "masa lalu" .Oleh karena itu
a
tidak boleh nol, dana + 1
tidak ditentukan oleh [expr.add] / 4 .sumber
new int[0]
menghasilkan apa yang saat ini disebut sebagai" nilai penunjuk "masa lalu" Ini tidak akurat. Tidak banyak diskusi. Satu orang menyarankan bahwa nilainya harus "penunjuk melewati akhir suatu objek", dan pernyataan ini dipertanyakan karena dalam kasus array dengan0
elemen, tidak ada objek yang melewati akhir dari objek.a + 1
tidak terdefinisi dalam hal apa pun, jadi poin Anda hanya berkaitan dengan apakaha
bisa nol?a + 1
tidak terdefinisi dan mungkin nilai pointer yang dihasilkan akan disebut "pointer past the end". Saya tidak mengatakan bahwa jawabannya salah. Ini sedikit tidak akurat karena dapat dipahami karena ada diskusi panjang dengan konsensus yang hanya menetapkan bahwa hasilnya adalah "penunjuk melewati akhir" sudah cukup untuk menyelesaikan masalah. Masalah dengan "pointer melewati ujung" adalah bahwa ia melewati akhir dari beberapa objek dan mengurangi1
dari nilai pointer tersebut memberikan satu pointer ke objek, yang mungkin seharusnya tidak menjadi kasus untuk array0
elemen.