Aplikasi tes sederhana:
cout << new int[0] << endl;
output:
0x876c0b8
Jadi sepertinya itu berfungsi. Apa yang dikatakan standar tentang ini? Apakah selalu legal untuk "mengalokasikan" blok memori kosong?
Aplikasi tes sederhana:
cout << new int[0] << endl;
output:
0x876c0b8
Jadi sepertinya itu berfungsi. Apa yang dikatakan standar tentang ini? Apakah selalu legal untuk "mengalokasikan" blok memori kosong?
Jawaban:
Dari 5.3.4 / 7
Ketika nilai ekspresi dalam deklarator langsung-baru adalah nol, fungsi alokasi dipanggil untuk mengalokasikan array tanpa elemen.
Dari 3.7.3.1/2
Efek dereferencing pointer dikembalikan sebagai permintaan untuk ukuran nol tidak ditentukan.
Juga
Bahkan jika ukuran ruang yang diminta [oleh baru] adalah nol, permintaan tersebut dapat gagal.
Itu berarti Anda bisa melakukannya, tetapi Anda tidak bisa secara legal (dengan cara yang didefinisikan dengan baik di semua platform) dereferensi memori yang Anda dapatkan - Anda hanya bisa meneruskannya ke array delete - dan Anda harus menghapusnya.
Berikut ini adalah catatan kaki yang menarik (yaitu bukan bagian normatif dari standar, tetapi termasuk untuk tujuan ekspositori) yang dilampirkan pada kalimat dari 3.7.3.1/2
[32] Tujuannya adalah agar operator baru () dapat diterapkan dengan memanggil malloc () atau calloc (), sehingga aturannya pada dasarnya sama. C ++ berbeda dari C yang membutuhkan nol permintaan untuk mengembalikan pointer non-null.]
new[]
dengan delete[]
- apa pun ukurannya. Khususnya, ketika Anda menelepon, new[i]
Anda membutuhkan sedikit lebih banyak memori daripada yang Anda coba alokasikan untuk menyimpan ukuran array (yang nantinya digunakan oleh delete[]
saat deallocating)
Ya, itu legal untuk mengalokasikan array berukuran nol seperti ini. Tetapi Anda juga harus menghapusnya.
int ar[0];
ilegal mengapa baru OK?
sizeof (type)
diharapkan untuk tidak pernah mengembalikan nol. Lihat misalnya: stackoverflow.com/questions/2632021/can-sizeof-return-0-zero
Apa yang dikatakan standar tentang ini? Apakah selalu legal untuk "mengalokasikan" blok memori kosong?
Setiap objek memiliki identitas unik, yaitu alamat unik, yang menyiratkan panjang non-nol (jumlah memori yang sebenarnya akan meningkat secara diam-diam, jika Anda meminta nol byte).
Jika Anda mengalokasikan lebih dari satu objek ini maka Anda akan menemukan mereka memiliki alamat yang berbeda.
operator []
juga menyimpan ukuran array di suatu tempat (lihat isocpp.org/wiki/faq/freestore-mgmt#num-elems-in-new-array ). Jadi jika implementasi mengalokasikan jumlah byte dengan data, itu bisa saja mengalokasikan untuk jumlah byte dan 0 byte untuk data, mengembalikan 1-past-last pointer.
operator new[]
harus mengembalikan pointer yang berbeda. BTW, new expression
memiliki beberapa aturan tambahan (5.3.4). Saya tidak dapat menemukan petunjuk bahwa new
dengan ukuran 0 sebenarnya diperlukan untuk mengalokasikan apa pun. Maaf, saya menurunkan suara karena saya menemukan bahwa jawaban Anda tidak menjawab pertanyaan, tetapi memberikan beberapa pernyataan kontroversial.
new[]
implementasi untuk mengembalikan alamat dalam rentang di mana tidak ada memori dinamis yang dipetakan, karenanya tidak benar-benar menggunakan memori apa pun (saat menggunakan ruang alamat)
while(!exitRequested) { char *p = new char[0]; delete [] p; }
loop tanpa pointer daur ulang akan runtuh menjadi debu sebelum bisa kehabisan ruang alamat, tetapi pada platform dengan pointer 32-bit yang akan menjadi asumsi jauh lebih masuk akal.
Ya, itu sepenuhnya legal untuk mengalokasikan 0
blok berukuran new
. Anda tidak bisa melakukan apa pun yang berguna dengan itu karena tidak ada data yang valid untuk Anda akses.int[0] = 5;
itu ilegal.
Namun, saya percaya bahwa standar memungkinkan untuk hal-hal seperti malloc(0)
kembaliNULL
.
Anda masih perlu delete []
pointer apa pun yang Anda dapatkan kembali dari alokasi juga.
Anehnya, C ++ mengharuskan operator baru mengembalikan pointer yang sah bahkan ketika nol byte diminta. (Memerlukan perilaku yang terdengar aneh ini menyederhanakan hal-hal lain di dalam bahasa ini.)
Saya menemukan Efektif C ++ Edisi Ketiga berkata seperti ini di "Item 51: Patuhi konvensi ketika menulis baru dan menghapus".
Saya jamin Anda bahwa int baru [0] membutuhkan ruang ekstra sejak saya mengujinya.
Misalnya, penggunaan memori
int **arr = new int*[1000000000];
secara signifikan lebih kecil dari
int **arr = new int*[1000000000];
for(int i =0; i < 1000000000; i++) {
arr[i]=new int[0];
}
Penggunaan memori dari potongan kode kedua dikurangi dari potongan kode pertama adalah memori yang digunakan untuk banyak int baru [0].