Properti pointer ke array panjang nol

21

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 ake nullptr?

Batsyeba
sumber
2
@ Fareanor: Anda dapat membaca adengan pasti (Anda tentu tidak bisa men-decere- nya).
Batsyeba
8
@RasmiRanjanNayak: Itu omong kosong.
Batsyeba
2
@RasmiRanjanNayak Ya ampun ... tidak
Ted Lyngmo
1
@ TedLyngmo: Ketika saya mengatakan "baca pointer di a + 1", apakah kode berikut ini auto b = a + 1;perilaku tidak terdefinisi? (Aku rasa ini).
Batsyeba
2
@Ayxan Saya kira dalam kasus di mana 0sebenarnya adalah hasil dari ekspresi yang Anda tidak akan tahu sampai runtime. Karena new int[0]aman, itu bisa menyelamatkan Anda khawatir tentang beberapa kasus percabangan / khusus. Bayangkan jika saya menginisialisasi std::vectordengan std::vector<int> v(0);.
scohe001

Jawaban:

3
    auto a = new int[0];

Berdasarkan [basic.compound.3] , nilai yang disimpan aharus salah satu dari yang berikut:

  1. Pointer ke objek (tipe int)
  2. Pointer melewati ujung objek
  3. Batal
  4. Tidak valid

Kita dapat mengesampingkan kemungkinan pertama karena tidak ada objek bertipe intdibangun. 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 asebagai 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 dapat deletepointer ini.) Jadi saya akan menghibur kedua kemungkinan dalam jawaban ini.

Di antara inisialisasi dan penghapusan salinan, apakah Anda diizinkan membaca pointer di a + 1?

Perilaku tidak terdefinisi, seperti yang ditentukan oleh [expr.add.4] , terlepas dari kemungkinan yang dari atas berlaku.

Jika aadalah pointer masa lalu, maka dianggap menunjuk ke elemen hipotetis pada indeks 0array tanpa elemen. Menambahkan integer juntuk adidefinisikan hanya ketika 0≤0+j≤n, di mana nadalah ukuran array. Dalam kasus kami, nadalah nol, sehingga jumlahnya a+jdidefinisikan hanya ketika jadalah 0. Secara khusus, menambahkan1 tidak ditentukan.

Jika atidak valid, maka kami dengan jelas jatuh ke dalam "Kalau tidak, perilaku tidak terdefinisi." (Tidak mengherankan, case yang didefinisikan hanya mencakup nilai pointer yang valid.)

Selanjutnya, apakah bahasa mengizinkan compiler untuk set ake nullptr?

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.

JaMiT
sumber
1
Jika itu adalah nilai pointer yang tidak valid, Anda akan memiliki masalah serius dari eel.is/c++draft/basic.stc#4
TC
@TC Benar, itu sangat menyiratkan bahwa itu tidak bisa menjadi nilai pointer yang tidak valid.
JaMiT
23

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 atidak boleh nol, dan a + 1tidak ditentukan oleh [expr.add] / 4 .

TC
sumber
4
"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" 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 dengan 0elemen, tidak ada objek yang melewati akhir dari objek.
Pengacara Bahasa
@LanguageLawyer sepertinya tidak ada keraguan yang a + 1tidak terdefinisi dalam hal apa pun, jadi poin Anda hanya berkaitan dengan apakah abisa nol?
MM
Tampaknya tidak ada perbedaan pendapat tentang semantik yang dimaksudkan, atau bahwa nama saat ini untuk kategori nilai penunjuk ini tidak cocok untuk skenario ini.
TC
@ MM Saya pikir itu a + 1tidak 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 mengurangi 1dari nilai pointer tersebut memberikan satu pointer ke objek, yang mungkin seharusnya tidak menjadi kasus untuk array 0elemen.
Pengacara Bahasa
2
@Bathsheba Apakah Anda pikir mungkin ada yang lebih otoritatif tentang kata-kata yang rusak?
Pengacara Bahasa