Erwägen
int main()
{
auto a = new int[0];
delete[] a; // So there's no memory leak
}
Dürfen Sie zwischen der Initialisierung und dem Löschen der Kopie den Zeiger auf lesen a + 1
?
Erlaubt die Sprache dem Compiler außerdem die Einstellung a
auf nullptr
?
c++
language-lawyer
Bathseba
quelle
quelle
a
sicher lesen (Sie können es sicher nicht dereferenzieren).a + 1
" sage , ist der folgende Codeauto b = a + 1;
undefiniertes Verhalten? (Ich denke, es ist).0
tatsächlich das Ergebnis eines Ausdrucks ist, den Sie erst zur Laufzeit kennen. Da diesnew int[0]
sicher ist, können Sie sich keine Sorgen über Verzweigungs- / Sonderfälle machen. Stellen Sie sich vor, ich würde einstd::vector
mit initialisierenstd::vector<int> v(0);
.Antworten:
Gemäß [basic.compound.3] ist der in
a
einer der folgenden sein:int
)Wir können die erste Möglichkeit ausschließen, da keine Objekte vom Typ
int
konstruiert wurden. Die dritte Möglichkeit ist ausgeschlossen, da in C ++ ein Nicht-Null-Zeiger zurückgegeben werden muss (siehe [basic.stc.dynamic.allocation.2] ). Wir haben also zwei Möglichkeiten: einen Zeiger hinter dem Ende eines Objekts oder einen ungültigen Zeiger.Ich würde gerne als
a
Zeiger über das Ende hinaus betrachten, aber ich habe keinen seriösen Hinweis, um dies endgültig festzustellen. (Es gibt jedoch eine starke Implikation in [basic.stc] , wenn Sie sehen, wie Siedelete
diesen Zeiger verwenden können.) Daher werde ich in dieser Antwort beide Möglichkeiten erläutern .Das Verhalten ist undefiniert, wie in [Ausdruck.add.4] vorgegeben , unabhängig davon, welche Möglichkeit von oben gilt.
Wenn
a
es sich um einen Past-the-End-Zeiger handelt, wird davon ausgegangen, dass er auf das hypothetische Element am Index0
eines Arrays ohne Elemente verweist. Das Hinzufügen der Ganzzahlj
zua
wird nur definiert, wenn0≤0+j≤n
, won
die Größe des Arrays ist. In unserem Falln
ist Null, daher wird die Summea+j
nur definiert, wennj
ist0
. Insbesondere ist das Hinzufügen1
undefiniert.Wenn
a
es ungültig ist, fallen wir sauber in "Andernfalls ist das Verhalten undefiniert." (Es überrascht nicht, dass die definierten Fälle nur gültige Zeigerwerte abdecken.)Nein . Aus dem oben erwähnten [basic.stc.dynamic.allocation.2] : „Wenn die Anforderung erfolgreich ist , wird der Wert durch eine austauschbare Zuteilungsfunktion ist ein Nicht-Null - Zeiger - Wert zurückgegeben“ . Es gibt auch eine Fußnote, in der darauf hingewiesen wird, dass C ++ (aber nicht C) einen Nicht-Null-Zeiger als Antwort auf eine Null-Anforderung benötigt.
quelle
Per jüngster Diskussion CWG Reflektor als Folge der redaktionellen Ausgabe 3178 ,
new int[0]
produziert , was derzeit einen genannt „past-the-end“ Zeigerwert .Daraus folgt, dass
a
dies nicht null sein kann unda + 1
durch [expr.add] / 4 nicht definiert ist .quelle
new int[0]
wird ein sogenannter" Past-the-End "-Zeigerwert erzeugt." Dies ist nicht korrekt. Es wurde nicht viel diskutiert. Eine Person schlug vor, dass der Wert "Zeiger nach dem Ende eines Objekts" sein sollte, und diese Aussage wurde in Frage gestellt, da bei einem Array mit0
Elementen kein Objekt nach dem Ende von vorhanden ist.a + 1
auf jeden Fall undefiniert ist. Ihr Punkt bezieht sich also nur darauf, oba
null sein kann.a + 1
ist undefiniert und vielleicht wird der resultierende Zeigerwert "Zeiger nach dem Ende" genannt. Ich sage nicht, dass die Antwort falsch ist. Es ist etwas ungenau, da es so verstanden werden könnte, dass es eine lange Diskussion mit einem Konsens gab, dass die bloße Angabe, dass das Ergebnis "Zeiger nach dem Ende" ist, ausreicht, um das Problem zu lösen. Das Problem mit "Zeiger hinter dem Ende" besteht darin, dass es hinter dem Ende eines Objekts liegt und das Subtrahieren1
von einem solchen Zeigerwert einen Zeiger auf das Objekt ergibt, was bei Arrays von0
Elementen wahrscheinlich nicht der Fall sein sollte .