Basit bir test uygulaması:
cout << new int[0] << endl;
çıktılar:
0x876c0b8
Yani çalışıyor gibi görünüyor. Standart bu konuda ne diyor? Boş bellek bloğunu "ayırmak" her zaman yasal mıdır?
Basit bir test uygulaması:
cout << new int[0] << endl;
çıktılar:
0x876c0b8
Yani çalışıyor gibi görünüyor. Standart bu konuda ne diyor? Boş bellek bloğunu "ayırmak" her zaman yasal mıdır?
Yanıtlar:
5.3.4 / 7'den itibaren
Direct-new-declarator içindeki ifadenin değeri sıfır olduğunda, eleman içermeyen bir dizi ayırmak için ayırma işlevi çağrılır.
3.7.3.1/2 itibaren
Sıfır boyut için bir istek olarak döndürülen bir işaretçinin kaydının silinmesinin etkisi tanımlanmamıştır.
Ayrıca
İstenen alanın boyutu [yeniye göre] sıfır olsa bile, istek başarısız olabilir.
Bu, bunu yapabileceğiniz anlamına gelir, ancak yasal olarak (tüm platformlarda iyi tanımlanmış bir şekilde) elde ettiğiniz belleği kullanamazsınız - yalnızca dizi silmeye geçirebilirsiniz - ve silmeniz gerekir.
3.7.3.1 / 2'den cümleye eklenmiş ilginç bir dipnot (yani standardın normatif bir parçası değil, ancak ifşa amaçlıdır)
[32. Amaç, malloc () veya calloc () öğesini çağırarak operatöre new () uygulanmasını sağlamaktır, bu nedenle kurallar büyük ölçüde aynıdır. C ++, boş olmayan bir işaretçi döndürmek için sıfır isteği gerektiren C'den farklıdır.]
new[]
bir ile delete[]
boyutu ne olursa olsun -. Özellikle, aradığınızda new[i]
, dizinin boyutunu saklamak için delete[]
Evet, bunun gibi sıfır boyutlu bir dizi ayırmak yasaldır. Ancak silmeniz de gerekir.
int ar[0];
yasadışı olduğunu biliyoruz, neden yeni OK?
sizeof (type)
sıfır asla geri bekleniyor. Örneğin bakınız: stackoverflow.com/questions/2632021/can-sizeof-return-0-zero
Standart bu konuda ne diyor? Boş bellek bloğunu "ayırmak" her zaman yasal mıdır?
Her nesnenin benzersiz bir kimliği vardır, yani sıfır olmayan bir uzunluk anlamına gelen benzersiz bir adres (sıfır bayt isterseniz gerçek bellek miktarı sessizce artar).
Bu nesnelerden birden fazlasını ayırdıysanız, bunların farklı adresleri olduğunu görürsünüz.
operator []
ayrıca dizinin boyutunu bir yerde saklar (bkz. isocpp.org/wiki/faq/freestore-mgmt#num-elems-in-new-array ). Dolayısıyla, uygulama bayt sayısını verilerle ayırırsa, yalnızca bayt sayısı ve 0 bayt için veri ayırabilir ve 1-son-son işaretçi döndürür.
operator new[]
farklı işaretçiler döndürmesi gerektiğini gerçekten (3.7.4.1/2) söylüyor . BTW, new expression
bazı ek kurallara sahiptir (5.3.4). new
0 boyutu ile aslında bir şey tahsis etmek için gereken herhangi bir ipucu bulamadım . Üzgünüm, cevap vermedim, çünkü cevabınızın soruları yanıtlamadığını, ancak bazı tartışmalı ifadeler sağladığını fark ettim.
new[]
uygulamanın dinamik bellek eşlenmemiş bir aralıktaki adresleri döndürmesi mümkün olabilir , bu nedenle gerçekten bellek kullanmaz (adres alanı kullanılırken)
while(!exitRequested) { char *p = new char[0]; delete [] p; }
geri dönüşüm işaretçileri olmadan bir döngü yürüten bir bilgisayarın adres alanı bitmeden toz haline geleceğini, ancak 32 bit işaretçileri olan bir platformda çok daha az makul varsayım.
Evet, 0
büyüklüğünde bir blok tahsis etmek tamamen yasaldır new
. Erişebileceğiniz geçerli bir veri olmadığı için bununla yararlı bir şey yapamazsınız.int[0] = 5;
yasadışı.
Ancak, standart malloc(0)
geri dönmek gibi şeyler için izin verir inanıyorum NULL
.
Yine delete []
de tahsisattan geri döndüğünüz işaretçiye ihtiyacınız olacaktır .
İlginçtir ki, C ++ sıfır bayt istendiğinde bile operatörün yeni bir işaretçi döndürmesini gerektirir. (Bu garip sondaj davranışını gerektirmek, dilin başka bir yerinde işleri kolaylaştırır.)
Buldum Etkili C ++ Third Edition ": Yeni ve sil yazarken uyun sözleşmeye Madde 51" de böyle söyledi.
Yeni int [0] 'un test ettiğim için size fazladan alan maliyeti sağladığını garanti ederim.
Örneğin, bellek kullanımı
int **arr = new int*[1000000000];
önemli ölçüde daha küçük
int **arr = new int*[1000000000];
for(int i =0; i < 1000000000; i++) {
arr[i]=new int[0];
}
İkinci kod snippet'inin eksi birinci kod snippet'inin bellek kullanımı, sayısız yeni int [0] için kullanılan bellektir.