Ist es immer noch sicher, nullptr in c ++ 0x zu löschen?

83

In c++03es ist ziemlich klar , dass ein Null - Zeiger zu löschen hat keine Wirkung. In der Tat wird ausdrücklich darauf hingewiesen §5.3.5/2:

In beiden Alternativen hat die Operation keine Auswirkung, wenn der Wert des Operanden "Löschen" der Nullzeiger ist.

Im aktuellen Entwurf für c++0xdiesen Satz scheint jedoch zu fehlen. Im Rest des Entwurfs konnte ich nur Sätze finden, die angeben, was passiert, wenn der Operand des Löschausdrucks nicht die Nullzeigerkonstante ist. Ist das Löschen des Nullzeigers noch definiert in c++0xund wenn ja, wo?

Anmerkungen:

Es gibt signifikante Indizien dafür, dass es immer noch gut definiert ist.

Erstens gibt es die zwei Sätze §5.3.5/2, die das besagen

In der ersten Alternative (Objekt löschen) kann der Wert des Operanden von delete ein Nullzeigerwert sein, ...

und

Bei der zweiten Alternative (Array löschen) kann der Wert des Operanden delete ein Nullzeigerwert sein oder ...

Diese besagen, dass der Operand null sein darf, definieren aber allein nicht, was passiert, wenn dies der Fall ist.

Zweitens ist eine Änderung der Bedeutung von delete 0eine wesentliche Änderung, und es ist sehr unwahrscheinlich, dass das Normungsgremium diese spezielle Änderung vornimmt. Darüber hinaus wird nicht erwähnt, dass dies eine bahnbrechende Änderung im Kompatibilitätsanhang (Anhang C) des c++0xEntwurfs ist. Anhang C ist jedoch ein informativer Abschnitt, daher hat dies keinen Einfluss auf die Auslegung der Norm.

Andererseits impliziert die Tatsache, dass das Löschen des Nullzeigers keine Auswirkung haben muss, eine zusätzliche Laufzeitprüfung. In vielen Codes kann der Operand niemals null sein, daher steht diese Laufzeitprüfung im Widerspruch zum Null-Overhead-Prinzip. Vielleicht hat das Komitee gerade beschlossen, das Verhalten zu ändern, um Standard-C ++ besser an die angegebenen Designziele der Sprache anzupassen.

Mankarse
quelle

Antworten:

100

5.3.5 / 7 sagt:

Wenn der Wert des Operanden des Löschausdrucks kein Nullzeigerwert ist, ruft der Löschausdruck eine Freigabefunktion auf (3.7.4.2). Andernfalls ist nicht angegeben, ob die Freigabefunktion aufgerufen wird.

Und 3.7.4.2/3 sagt:

Der Wert des ersten Arguments, das einer Freigabefunktion übergeben wird, kann ein Nullzeigerwert sein. Wenn dies der Fall ist und die Freigabefunktion in der Standardbibliothek bereitgestellt wird, hat der Aufruf keine Auswirkung.

Das Verhalten ist also gut definiert, solange die Standard-Freigabefunktion verwendet wird oder eine vom Benutzer bereitgestellte Freigabefunktion Nullzeiger korrekt verarbeitet.

Interjay
quelle
9
Seit C ++ 14 "Wenn der Ausdruck einen Nullzeigerwert ergibt, werden keine Destruktoren aufgerufen und die Freigabefunktion wird nicht aufgerufen."
Wormer
2
@Wormer Ich denke nicht, dass diese Seite korrekt ist. Der C ++ 14-Standard sagt immer noch "es ist nicht spezifiziert, ob die Freigabefunktion aufgerufen wird", wenn der Zeiger null ist (5.3.5 / 7).
Interjay
1
Abgesehen davon ist es nicht sicher, fclose () für einen Null-Dateizeiger aufzurufen. Unter Ubuntu (und möglicherweise anderen Betriebssystemen) verursacht fclose (NULL) einen Segmentierungsfehler.
Gerry Beauregard
7

Andererseits impliziert die Tatsache, dass das Löschen des Nullzeigers keine Auswirkung haben muss, eine zusätzliche Laufzeitprüfung.

Der neue Wortlaut entfernt diese Laufzeitprüfung für einen Nullzeiger nicht. Umgekehrt: Der Standardentwurf kommt der Aussage noch näher, dass eine Implementierung einen Nullzeigertest durchführen muss , um konform zu sein.

Ebenfalls bemerkenswert: Der alte Standard widersprach sich darin, dass er sagte (5.3.5 / 2), dass "wenn der Wert des Operanden von delete der Nullzeiger ist, die Operation keine Wirkung hat", sagte aber später, dass (5.3.5 / 7) Der "Löschausdruck ruft eine Freigabefunktion auf." Das Aufrufen einer Funktion ist ein Effekt. Dies ist insbesondere deshalb so, weil die aufgerufene Funktion möglicherweise überschrieben wird operator delete.

Der neue Wortlaut beseitigt diesen Widerspruch und überlässt es explizit der Implementierung, ob die Freigabefunktion beim Löschen eines Nullzeigers aufgerufen wird.

David Hammen
quelle