2013-05-16 42 views

Odpowiedz

10

Zarówno stała nullptr (który jest typu nullptr_t) i stała 0 niejawnie przekonwertować na wartość pustą dowolnego typu wskaźnika. Tak więc porównanie z jednym z nich zadziała i jest technicznie w porządku. Nawiasem mówiąc, oznacza to, że dynamic_cast nie zwraca żadnego z nich, zwraca wartość pustą dla określonego typu wskaźnika.

Najlepiej jest uzyskać nawyk używania nullptr zamiast 0. Z tego, co wiem, jest to naprawdę konieczne dla właściwej rozdzielczości przeciążenia (np. Jedna przeciążenie pobiera int, a druga zajmuje char*). Aby zachować spójność, najlepiej będzie unikać unikania 0.

Co mam na myśli przez "wartość zerową typu wskaźnika"?

Rozważ zmienną char * ptr. Jego typ jest (nie zaskakuje) char *. Typ nullptr to specjalny typ nullptr_t. Kiedy więc napisać coś jak ptr = nullptr, niektóre rzeczy techniczne muszą zdarzyć

  1. nullptr musi być niejawnie konwertowane do char *.
  2. Wynik tej konwersji jest ustawiony jako nowa wartość ptr.

zerowa wartość char * jest wynikiem konwersji nullptr do char *. Koncepcyjnie nadal jest to nullptr, ale z innym typem (char *). Ta wartość pusta jest różna od wartości pustej int * lub string * lub dowolnego innego typu wskaźnika. Mamy tendencję do myślenia o tych zerowych wartościach jako nullptr (lub 0), ale każda z nich jest naprawdę odrębną wartością od innego typu. (Nawiasem mówiąc, ta sama konwersja dzieje się dla porównania przy użyciu ==).

Chociaż może to brzmieć jak szczegóły nitpicking, to bardzo ważne w rozdzielczości przeciążenia:

void foo(char * ptr) { ... } 
void foo(int i) { ... } 
void foo(nullptr_t ptr) { ... } 

int main() 
{ 
    foo(0); // Calls void foo(int), since 0 is an int 
    foo(nullptr); // Calls void foo(nullptr_t), since nullptr is a nullptr_t 
    foo(new char('c')); // Calls void foo(char *), since new char('c') is a char* 
} 

lub podczas przypisywania niepowiązanych wartości null:

char * c_ptr = nullptr; // Okay 
int * i_ptr1 = nullptr; // Okay 
int * i_ptr2 = c_ptr; // COMPILER ERROR HERE 
+0

Czy możesz zdefiniować, co masz na myśli przez wartość pustą typu wskaźnika? Czym różni się od 0 lub nullptr? – Patrick

+0

@Patrick: Zamiast odpowiedzieć na to w komentarzu, dołączę do mojej odpowiedzi. Myślę, że jest to wystarczająco istotne dla pytania. –

+0

Interesujące. Więc kiedy robię 'if (nullptr == dynamic_cast (p))', czy 'nullptr' najpierw jest konwertowany na wartość pustą' foo * ', a następnie dokonuje się porównania? – Patrick

5

Ocenić wynik w kontekście logicznym:

Base * p = get(); 

if (Derived * q = dynamic_cast<Derived *>(p)) 
{ 
    q->derived_method(); 
} 
else 
{ 
    // *p isn't of type Derived 
} 

(. To działa w każdej wersji C++)

+0

Lubię swoje rozwiązanie, ale Ken Wayne bardziej bezpośrednio odpowiedział moje pytanie, więc zaznaczam jego jako odpowiedź. Dzięki za odpowiedź! – Patrick

+0

Jest to prawdopodobnie lepsza forma użycia (nawet jeśli 'nullptr' zawsze istniała), ponieważ działa na więcej niż tylko typy, które porównują do' nullptr'.Działa dla każdego typu, który ma pojęcie pustki, wyrażone jako konwersja do 'bool', np.' Opcjonalnie '. Myślę też, że wygląda ładniej dla typów takich jak 'std :: function', które są porównywalne do' nullptr', ale które w rzeczywistości nie są typami wskaźnikowymi! –