Eine einfache Test-App:
cout << new int[0] << endl;
Ausgänge:
0x876c0b8
Es sieht also so aus, als ob es funktioniert. Was sagt der Standard dazu? Ist es immer legal, einen leeren Speicherblock "zuzuweisen"?
Eine einfache Test-App:
cout << new int[0] << endl;
Ausgänge:
0x876c0b8
Es sieht also so aus, als ob es funktioniert. Was sagt der Standard dazu? Ist es immer legal, einen leeren Speicherblock "zuzuweisen"?
Antworten:
Ab 5.3.4 / 7
Wenn der Wert des Ausdrucks in einem Direct-New-Deklarator Null ist, wird die Zuordnungsfunktion aufgerufen, um ein Array ohne Elemente zuzuweisen.
Ab 3.7.3.1/2
Der Effekt der Dereferenzierung eines Zeigers, der als Anforderung für die Größe Null zurückgegeben wird, ist undefiniert.
Ebenfalls
Selbst wenn die Größe des angeforderten Speicherplatzes [von new] Null ist, kann die Anforderung fehlschlagen.
Das bedeutet, dass Sie dies tun können, aber Sie können den Speicher, den Sie erhalten, nicht legal (auf alle Plattformen genau definiert) dereferenzieren - Sie können ihn nur an Array Delete übergeben - und Sie sollten ihn löschen.
Hier ist eine interessante Fußnote (dh kein normativer Teil des Standards, aber zu Expository-Zwecken enthalten), die dem Satz vom 3.7.3.1/2 beigefügt ist
[32. Der Operator new () soll durch Aufrufen von malloc () oder calloc () implementiert werden können, sodass die Regeln im Wesentlichen dieselben sind. C ++ unterscheidet sich von C darin, dass eine Nullanforderung erforderlich ist, um einen Nicht-Nullzeiger zurückzugeben.]
new[]
mit a ausgleichen delete[]
- unabhängig von der Größe. Insbesondere wenn Sie anrufen new[i]
, benötigen Sie etwas mehr Speicher als den, den Sie zuweisen möchten, um die Größe des Arrays zu speichern (das später delete[]
bei der Freigabe verwendet wird)
Ja, es ist legal, ein Array mit der Größe Null wie dieses zuzuweisen. Sie müssen es aber auch löschen.
int ar[0];
das illegal ist, warum ist neues OK?
sizeof (type)
wird erwartet, dass es niemals Null zurückgibt. Siehe zum Beispiel: stackoverflow.com/questions/2632021/can-sizeof-return-0-zero
Was sagt der Standard dazu? Ist es immer legal, einen leeren Speicherblock "zuzuweisen"?
Jedes Objekt hat eine eindeutige Identität, dh eine eindeutige Adresse, die eine Länge ungleich Null impliziert (die tatsächliche Speichermenge wird stillschweigend erhöht, wenn Sie nach null Byte fragen).
Wenn Sie mehr als eines dieser Objekte zugewiesen haben, werden sie unterschiedliche Adressen haben.
operator []
speichert auch die Größe des Arrays irgendwo (siehe isocpp.org/wiki/faq/freestore-mgmt#num-elems-in-new-array ). Wenn die Implementierung den Daten also die Byteanzahl zuweist, kann sie nur die Byteanzahl und 0 Bytes für die Daten zuweisen und einen 1-nach-letzten-Zeiger zurückgeben.
operator new[]
unterschiedliche Zeiger zurückgeben sollen. BTW, das new expression
hat einige zusätzliche Regeln (5.3.4). Ich konnte keine Ahnung finden , die new
mit 0 Größe tatsächlich benötigt etwas zu vergeben. Entschuldigung, ich habe abgelehnt, weil ich finde, dass Ihre Antwort nicht die Fragen beantwortet, sondern einige kontroverse Aussagen enthält.
new[]
Implementierung Adressen in einem Bereich
while(!exitRequested) { char *p = new char[0]; delete [] p; }
Schleife ohne Recycling von Zeigern ausführt, in Staub zerfällt, bevor ihm möglicherweise der Adressraum ausgeht. Auf einer Plattform mit 32-Bit-Zeigern wäre dies jedoch ein weit weniger vernünftige Annahme.
Ja, es ist völlig legal, einen 0
Block mit Größe zuzuweisen new
. Sie können damit einfach nichts Nützliches anfangen, da Sie keine gültigen Daten haben, auf die Sie zugreifen können. int[0] = 5;
ist illegal.
Ich glaube jedoch, dass der Standard Dinge wie malloc(0)
die Rückkehr zulässt NULL
.
Sie benötigen weiterhin den delete []
Zeiger, den Sie von der Zuordnung erhalten.
Seltsamerweise erfordert C ++, dass der Operator new einen legitimen Zeiger zurückgibt, selbst wenn null Bytes angefordert werden. (Das Erfordernis dieses seltsam klingenden Verhaltens vereinfacht die Dinge an anderer Stelle in der Sprache.)
Ich fand, dass Effective C ++ Third Edition in "Punkt 51: Konvention beim Schreiben von Neuem und Löschen einhalten".
Ich garantiere Ihnen, dass new int [0] Sie zusätzlichen Speicherplatz kostet, da ich es getestet habe.
Zum Beispiel die Speichernutzung von
int **arr = new int*[1000000000];
ist deutlich kleiner als
int **arr = new int*[1000000000];
for(int i =0; i < 1000000000; i++) {
arr[i]=new int[0];
}
Die Speichernutzung des zweiten Code-Snippets minus der des ersten Code-Snippets ist der Speicher, der für die zahlreichen neuen int [0] verwendet wird.