Zurück in C ++ 03 wurde ein Nullzeiger durch die ISO-Spezifikation (§4.10 / 1) als definiert
Eine Nullzeigerkonstante ist ein integraler Konstantenausdruck (5.19) rWert vom Integer-Typ, der zu Null ausgewertet wird.
Deshalb können Sie in C ++ schreiben
int* ptr = 0;
In C ist diese Regel ähnlich, aber etwas anders (§6.3.2.3 / 3):
Ein ganzzahliger Konstantenausdruck mit dem Wert 0 oder ein solcher Ausdruck, der in einen Typ umgewandelt wird
void *
, wird als Nullzeigerkonstante bezeichnet.55) Wenn eine Nullzeigerkonstante in einen Zeigertyp konvertiert wird, wird der resultierende Zeiger, der als Nullzeiger bezeichnet wird, garantiert Vergleiche ungleich einem Zeiger auf ein Objekt oder eine Funktion.
Folglich beides
int* ptr = 0;
und
int* ptr = (void *)0
sind legal. Ich vermute jedoch, dass die void*
Besetzung hier ist, so dass Aussagen mögen
int x = NULL;
Erstellen Sie auf den meisten Systemen eine Compiler-Warnung. In C ++ wäre dies nicht legal, da Sie a ohne Umwandlung nicht implizit in einen void*
anderen Zeigertyp konvertieren können . Dies ist beispielsweise illegal:
int* ptr = (void*)0;
Dies führt jedoch zu Problemen aufgrund des Codes
int x = NULL;
ist legal C ++. Aus diesem Grund und der daraus resultierenden Verwirrung (und einem anderen Fall, der später gezeigt wird) gibt es seit C ++ 11 ein Schlüsselwort, nullptr
das einen Nullzeiger darstellt:
int* ptr = nullptr;
Dies hat keines der oben genannten Probleme.
Der andere Vorteil von nullptr
über 0 ist, dass es mit dem System vom Typ C ++ besser spielt. Angenommen, ich habe diese beiden Funktionen:
void DoSomething(int x);
void DoSomething(char* x);
Wenn ich anrufe
DoSomething(NULL)
Es ist gleichbedeutend mit
DoSomething(0);
das ruft DoSomething(int)
statt der erwarteten DoSomething(char*)
. Mit nullptr
konnte ich jedoch schreiben
DoSomething(nullptr)
Und es wird die DoSomething(char*)
Funktion wie erwartet aufrufen .
Angenommen, ich habe ein vector<Object*>
und möchte jedes Element als Nullzeiger festlegen. Mit dem std::fill
Algorithmus könnte ich versuchen zu schreiben
std::fill(v.begin(), v.end(), NULL);
Dies wird jedoch nicht kompiliert, da das Vorlagensystem NULL
als int
und nicht als Zeiger behandelt wird. Um dies zu beheben, müsste ich schreiben
std::fill(v.begin(), v.end(), (Object*)NULL);
Dies ist hässlich und macht den Zweck des Vorlagensystems etwas zunichte. Um dies zu beheben, kann ich verwenden nullptr
:
std::fill(v.begin(), v.end(), nullptr);
Und da nullptr
bekannt ist, dass ein Typ einem Nullzeiger entspricht (speziell std::nullptr_t
), wird dieser korrekt kompiliert.
Hoffe das hilft!
void*
in einen beliebigen Zeigertyp umwandeln können und in C ++ nicht.