Was genau ist nullptr?

Lesezeit: 9 Minuten

Was genau ist nullptr
Khaled Alshaya

Wir haben jetzt C++11 mit vielen neuen Features. Ein interessantes und verwirrendes (zumindest für mich) ist das Neue nullptr.

Nun, keine Notwendigkeit mehr für das fiese Makro NULL.

int* x = nullptr;
myclass* obj = nullptr;

Trotzdem verstehe ich nicht wie nullptr funktioniert. Zum Beispiel, Wikipedia-Artikel sagt:

C++11 korrigiert dies durch die Einführung eines neuen Stichwort um als distinguierte Nullzeigerkonstante zu dienen: nullptr. Es ist von Geben Sie nullptr_t ein, die implizit konvertierbar und mit jedem Zeigertyp oder Zeiger-auf-Member-Typ vergleichbar ist. Es ist nicht implizit konvertierbar oder mit ganzzahligen Typen vergleichbar, mit Ausnahme von bool.

Wie ist es ein Schlüsselwort und eine Instanz eines Typs?

Haben Sie auch ein anderes Beispiel (neben dem Wikipedia-Beispiel), wo nullptr ist dem guten alten überlegen 0?

  • verwandte Tatsache: nullptr wird auch verwendet, um einen Nullverweis für verwaltete Handles in C++/CLI darzustellen.

    – mmx

    15. August 2009 um 16:52 Uhr

  • Ist nullptr_t garantiert nur ein Mitglied, nullptr? Also, wenn eine Funktion zurückgegeben wird nullptr_tdann weiß der Compiler bereits, welcher Wert zurückgegeben wird, unabhängig vom Hauptteil der Funktion?

    – Aaron McDaid

    28. Juli 2015 um 11:02 Uhr

  • @AaronMcDaid std::nullptr_t kann instanziiert werden, aber alle Instanzen sind identisch mit nullptr weil der Typ definiert ist als typedef decltype(nullptr) nullptr_t. Ich glaube, der Hauptgrund, warum der Typ existiert, ist, dass Funktionen speziell zum Fangen überladen werden können nullptr, im Bedarfsfall. Sehen Hier zum Beispiel.

    – Justin Time – Wiedereinsetzung von Monica

    14. Juni 2016 um 23:26 Uhr

  • 0 war nie ein Null-Zeiger, Null-Zeiger ist ein Zeiger, mit dem man umgehen kann Gießen Nullliteral auf den Zeigertyp, und es zeigt nicht auf irgendein vorhandenes Objekt per Definition.

    – Swift – Friday Pie

    6. März 2017 um 7:26 Uhr

  • @Nils Der Punkt drückt Absicht aus!

    – Neugieriger

    8. Juli 2019 um 1:06 Uhr

Was genau ist nullptr
Johannes Schaub – litb

Wie ist es ein Schlüsselwort und eine Instanz eines Typs?

Das ist nicht überraschend. Beide true und false sind Schlüsselwörter und haben als Literale einen Typ ( bool ). nullptr ist ein Zeiger-Literal des Typs std::nullptr_tund es ist ein Prvalue (Sie können die Adresse nicht mit verwenden &).

  • 4.10 über die Zeigerkonvertierung sagt, dass ein Prvalue vom Typ std::nullptr_t eine Nullzeigerkonstante ist und in die eine ganzzahlige Nullzeigerkonstante konvertiert werden kann std::nullptr_t. Die entgegengesetzte Richtung ist nicht erlaubt. Dies ermöglicht das Überladen einer Funktion sowohl für Zeiger als auch für ganze Zahlen und das Übergeben nullptr um die Zeigerversion auszuwählen. Vorbeigehen NULL oder 0 würde das verwirrend auswählen int Ausführung.

  • Eine Besetzung von nullptr_t zu einem ganzzahligen Typ braucht a reinterpret_castund hat die gleiche Semantik wie eine Besetzung von (void*)0 zu einem ganzzahligen Typ (Mapping-Implementierung definiert). EIN reinterpret_cast kann nicht konvertieren nullptr_t zu jedem Zeigertyp. Verlassen Sie sich wenn möglich auf die implizite Konvertierung oder verwenden Sie static_cast.

  • Das verlangt die Norm sizeof(nullptr_t) sein sizeof(void*).

  • Oh, nachdem ich nachgesehen habe, scheint es mir, dass der Bedingungsoperator in Fällen wie 0 nicht in nullptr konvertieren kann cond ? nullptr : 0;. Aus meiner Antwort entfernt.

    – Johannes Schaub – litb

    15. August 2009 um 17:23 Uhr

  • Beachten Sie, dass NULL ist nicht einmal garantiert 0. Es kann sein 0Lin diesem Fall ein Anruf an void f(int); void f(char *); wird zweideutig sein. nullptr wird immer die Zeigerversion bevorzugen und niemals die aufrufen int ein. Beachte das auch nullptr ist umwandelbar zu bool (der Entwurf sagt das bei 4.12).

    – Johannes Schaub – litb

    15. August 2009 um 18:09 Uhr

  • @litb: also in Bezug auf f (int) und f (void *) – wird f (0) immer noch mehrdeutig sein?

    – Steve Torheit

    15. August 2009 um 20:48 Uhr

  • @Steve, nein das wird das nennen int Ausführung. Aber f(0L) ist zweideutig, weil long -> int ebenso gut wie long -> void* ist beides gleich teuer. Also wenn NULL ist 0L auf Ihrem Compiler, dann ein Aufruf f(NULL) angesichts dieser beiden Funktionen mehrdeutig sein. Nicht so mit nullptr selbstverständlich.

    – Johannes Schaub – litb

    15. August 2009 um 22:14 Uhr

  • @SvenS Es darf nicht als definiert werden (void*)0 in C++. Aber es kann als beliebige Nullzeigerkonstante definiert werden, die jede ganzzahlige Konstante mit dem Wert 0 und nullptr erfüllen. Also ganz sicher nicht Wille aber kann. (Sie haben übrigens vergessen, mich anzupingen.)

    – Deduplizierer

    24. Februar 2016 um 1:31 Uhr

Was genau ist nullptr
Gabriel Staples

Warum nullptr in C++11? Was ist es? Warum ist NULL nicht ausreichend?

C++-Experte Alex Allain sagt es hier perfekt (meine Hervorhebung fett hinzugefügt):

…stellen Sie sich vor, Sie haben die folgenden zwei Funktionsdeklarationen:

void func(int n); 
void func(char *s);
 
func( NULL ); // guess which function gets called?

Obwohl es so aussieht, als würde die zweite Funktion aufgerufen werden – schließlich übergeben Sie etwas, das wie ein Zeiger aussieht –, ist es wirklich die erste Funktion, die aufgerufen wird! Das Problem ist, dass, weil NULL gleich 0 und 0 eine ganze Zahl ist, stattdessen die erste Version von func aufgerufen wird. So etwas passiert zwar nicht immer, aber wenn es passiert, ist es extrem frustrierend und verwirrend. Wenn Sie die Details nicht kennen, könnte es durchaus wie ein Compiler-Fehler aussehen. Eine Sprachfunktion, die wie ein Compiler-Bug aussieht, ist, nun ja, nichts, was Sie wollen.

Geben Sie nullptr ein. In C++11 ist nullptr ein neues Schlüsselwort, das verwendet werden kann (und sollte!), um NULL-Zeiger darzustellen; Mit anderen Worten, wo immer Sie zuvor NULL geschrieben haben, sollten Sie stattdessen nullptr verwenden. Es ist Ihnen, dem Programmierer, nicht mehr klar(jeder weiß, was NULL bedeutet), aber es ist expliziter für den Compilerwodurch 0s nicht mehr überall verwendet werden, um eine besondere Bedeutung zu haben, wenn sie als Zeiger verwendet werden.

Allain beendet seinen Artikel mit:

Unabhängig davon lautet die Faustregel für C++11, dass man einfach damit anfangen sollte nullptr wann immer Sie es sonst verwendet hätten NULL in der Vergangenheit.

(Meine Worte):

Vergiss das schließlich nicht nullptr ist ein Objekt – eine Klasse. Es kann überall verwendet werden NULL wurde zuvor verwendet, aber wenn Sie seinen Typ aus irgendeinem Grund benötigen, kann sein Typ mit extrahiert werden decltype(nullptr)oder direkt beschrieben als std::nullptr_tdas ist einfach ein typedef von decltype(nullptr)wie hier gezeigt:

Im Header definiert <cstddef>:

Sehen:

  1. https://en.cppreference.com/w/cpp/types/nullptr_t
  2. und https://en.cppreference.com/w/cpp/header/cstddef
namespace std
{
typedef decltype(nullptr) nullptr_t; // (since C++11)
// OR (same thing, but using the C++ keyword `using` instead of the C and C++ 
// keyword `typedef`):
using nullptr_t = decltype(nullptr); // (since C++11)
} // namespace std

Verweise:

  1. Cprogramming.com: Bessere Typen in C++11 – nullptr, Enum-Klassen (stark typisierte Enumerationen) und cstdint
  2. https://en.cppreference.com/w/cpp/language/decltype
  3. https://en.cppreference.com/w/cpp/types/nullptr_t
  4. https://en.cppreference.com/w/cpp/header/cstddef
  5. https://en.cppreference.com/w/cpp/keyword/using
  6. https://en.cppreference.com/w/cpp/keyword/typedef

1647205811 585 Was genau ist nullptr
Nik

Von nullptr: Ein typsicherer und eindeutiger Nullzeiger:

Das neue C++09-Schlüsselwort nullptr bezeichnet eine rvalue-Konstante, die als universelles Nullzeiger-Literal dient und das fehlerhafte und schwach typisierte Literal 0 und das berüchtigte NULL-Makro ersetzt. nullptr macht damit Schluss mit mehr als 30 Jahren Peinlichkeit, Mehrdeutigkeit und Bugs. Die folgenden Abschnitte stellen die nullptr-Funktion vor und zeigen, wie sie die Beschwerden von NULL und 0 beheben kann.

Andere Referenzen:

  • C++09? Wurde es nicht vor August 2011 als C++0x bezeichnet?

    – Michael Dorst

    12. März 2013 um 19:10 Uhr

  • @anthropomorphic Nun, das ist sein Zweck. C++0x wurde verwendet, während es noch in Arbeit war, da nicht bekannt war, ob es 2008 oder 2009 fertig sein würde. Beachten Sie, dass es tatsächlich C++0B wurde, was C++11 bedeutet. Sehen stroustrup.com/C++11FAQ.html

    – mxmlnkn

    14. April 2016 um 9:59 Uhr


1647205812 980 Was genau ist nullptr
Motti

Wenn Sie eine Funktion haben, die Zeiger auf mehr als einen Typ empfangen kann, rufen Sie sie mit auf NULL ist nicht eindeutig. Die Art und Weise, wie dies jetzt umgangen wird, ist sehr hackig, indem ein Int akzeptiert und angenommen wird, dass dies der Fall ist NULL.

template <class T>
class ptr {
    T* p_;
    public:
        ptr(T* p) : p_(p) {}

        template <class U>
        ptr(U* u) : p_(dynamic_cast<T*>(u)) { }

        // Without this ptr<T> p(NULL) would be ambiguous
        ptr(int null) : p_(NULL)  { assert(null == NULL); }
};

Im C++11 Sie könnten überlasten nullptr_t damit ptr<T> p(42); wäre eher ein Kompilierzeitfehler als ein Laufzeitfehler assert.

ptr(std::nullptr_t) : p_(nullptr)  {  }

1647205812 871 Was genau ist nullptr
Benutzer633658

nullptr kann keinem ganzzahligen Typ wie an zugewiesen werden int aber nur ein Zeigertyp; entweder ein eingebauter Zeigertyp wie z int *ptr oder ein intelligenter Zeiger wie z std::shared_ptr<T>

Ich glaube, das ist eine wichtige Unterscheidung, weil NULL kann weiterhin sowohl einem ganzzahligen Typ als auch einem Zeiger as zugewiesen werden NULL ist ein Makro, erweitert zu 0 was sowohl als Anfangswert für an dienen kann int sowie ein Zeiger.

  • Beachten Sie, dass diese Antwort falsch ist. NULL wird nicht garantiert erweitert 0.

    – LF

    4. Juli 2019 um 7:26 Uhr

Nun, andere Sprachen haben reservierte Wörter, die Instanzen von Typen sind. Python zum Beispiel:

>>> None = 5
  File "<stdin>", line 1
SyntaxError: assignment to None
>>> type(None)
<type 'NoneType'>

Dies ist eigentlich ein ziemlich enger Vergleich, weil None wird normalerweise für etwas verwendet, das nicht initialisiert wurde, aber gleichzeitig Vergleiche wie z None == 0 sind falsch.

Auf der anderen Seite, in Ebene C, NULL == 0 würde echtes IIRC zurückgeben, weil NULL ist nur ein Makro, das 0 zurückgibt, was immer eine ungültige Adresse ist (AFAIK).

  • Beachten Sie, dass diese Antwort falsch ist. NULL wird nicht garantiert erweitert 0.

    – LF

    4. Juli 2019 um 7:26 Uhr

1647205813 527 Was genau ist nullptr
das Schwein

Haben Sie auch ein anderes Beispiel (neben dem Wikipedia-Beispiel), wo nullptr ist der guten alten 0 überlegen?

Jawohl. Es ist auch ein (vereinfachtes) reales Beispiel, das in unserem Produktionscode vorkam. Es fiel nur auf, weil gcc beim Crosscompilieren auf eine Plattform mit unterschiedlicher Registerbreite eine Warnung ausgeben konnte (immer noch nicht genau, warum nur beim Crosscompiling von x86_64 auf x86, warnt warning: converting to non-pointer type 'int' from NULL):

Betrachten Sie diesen Code (C++03):

#include <iostream>

struct B {};

struct A
{
    operator B*() {return 0;}
    operator bool() {return true;}
};

int main()
{
    A a;
    B* pb = 0;
    typedef void* null_ptr_t;
    null_ptr_t null = 0;

    std::cout << "(a == pb): " << (a == pb) << std::endl;
    std::cout << "(a == 0): " << (a == 0) << std::endl; // no warning
    std::cout << "(a == NULL): " << (a == NULL) << std::endl; // warns sometimes
    std::cout << "(a == null): " << (a == null) << std::endl;
}

Es ergibt diese Ausgabe:

(a == pb): 1
(a == 0): 0
(a == NULL): 0
(a == null): 1

  • Ich sehe nicht, wie sich dies verbessert, wenn nullptr (und C++ 11) verwendet wird. Wenn Sie pb auf nullptr setzen, ist der erste Vergleich immer noch wahr (beim Vergleichen von Äpfeln mit Birnen …). Der zweite Fall ist noch schlimmer: Wenn Sie a mit nullptr vergleichen, wird a in B* umgewandelt und dann wieder als wahr ausgewertet (bevor es in bool umgewandelt und der Ausdruck als falsch ausgewertet wurde). Das Ganze erinnert mich an JavaScript und ich frage mich, ob wir in Zukunft === in C++ bekommen 🙁

    – Nils

    25. April 2018 um 11:01 Uhr

999020cookie-checkWas genau ist nullptr?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy