2012-07-01 12 views
30

W kilku starszych projektach kodu, kiedy nigdy nie słyszałem o inteligentnych wskaźnikach, zawsze gdy potrzebowałem sprawdzenia, czy wskaźnik nadal wskazywał na prawidłowy obiekt, zawsze robiłem coś takiego ...Nullptr i sprawdzanie, czy wskaźnik wskazuje na poprawny obiekt

object * meh = new object; 
if(meh) 
    meh->member; 

Albo kiedy potrzebne, aby usunąć obiekt bezpiecznie, coś jak ten

if(meh) 
{ 
    delete meh; 
    meh = 0; 
} 

Cóż, teraz nauczyłem się o problemach, które mogą wyniknąć z wykorzystaniem obiektów i wskaźniki w wyrażeniach boolowskich, zarówno z liczbami dosłownymi, w sposób trudny:. A teraz dowiedziałem się również o niezbyt nowej, ale całkiem fajnej funkcji słowa kluczowego C++, nullptr. Ale teraz jestem ciekawy.

Ja już przeszedł i poprawione większość mojego kodu tak, że na przykład, gdy usuwanie obiektów mam teraz napisać

if(meh) 
{ 
    delete meh; 
    meh = nullptr; 
} 

Teraz zastanawiam o wartości logicznej. Po przejechaniu tylko powiedzieć, int w instrukcji if jak ta,

int meh; 
if(meh) 

Potem niejawnie sprawdza zera bez potrzeby dodawania go napisać.

if(meh == 0) // does the exact same check 

Teraz, czy C++ zrobi to samo dla wskaźników? Jeśli przekazać znak tak jak w instrukcji if?

char * meh; 
if(meh) 

Następnie domyślnie porównać go z nullptr? Ze względu na to, jak długo pisałem te wyrażenia, takie jest to, że w tej chwili należy sprawdzić, czy wskaźniki są poprawne przed użyciem, wpisując, jeśli (obiekt *), a następnie wywołując jego członków. Jeśli nie jest to funkcja, dlaczego nie? Zbyt trudne do wdrożenia? Rozwiązałbym niektóre problemy, usuwając kolejny mały sposób na zepsucie kodu.

+22

Nie musisz ** nie ** potrzebować sprawdzać wskaźników przed 'delete'ing. Całkowicie bezpieczne jest "usuwanie" 'nullptr'. –

+1

W twoim ostatnim przykładzie, masz na myśli 'char * meh = nullptr; jeśli (meh) '? Wskaźnik jest niezainicjowany. –

+3

Wynik twojego "nowego" wyrażenia nigdy nie będzie mieć wartości null, zamiast tego używane są wyjątki. Jak wspomniano, usunięcie null jest w porządku, to nic nie robi. Zasadniczo lepiej nie resetować wartości wskaźników do wartości null. Ostatni raz, gdy jest używany, powinien być ostatnim razem, gdy nie jest pusty, więc dostęp do usuniętego wskaźnika powinien być uważany za błąd; ustawienie go na wartość null to ukrywa. – GManNickG

Odpowiedz

32

W języku C wszystko, co nie jest równe 0, jest prawdziwe. Z pewnością można użyć:

if (ptrToObject) 
    ptrToObject->doSomething(); 

na bezpieczne wskaźniki dereferencyjne.

C++ 11 nieco zmienia grę, nullptr_t jest typem, którego jest nullptr; reprezentacja nullptr_t jest zależna od implementacji. Tak więc kompilator może zdefiniować, ale chce. trzeba to zrobić tylko na pewno można go egzekwować prawidłowe ograniczenie odlewania nullptr_t do różnych rodzajów - z których logiczna jest dozwolone - i upewnij się, że można go odróżnić nullptr_t i 0.

Więc nullptr będzie poprawnie i niejawnie rzutować na booleanfalse, o ile kompilator będzie zgodny ze specyfikacją języka C++ 11. Powyższy fragment nadal działa.

Po usunięciu obiektu, do którego się odwołuje, nic się nie zmienia.

delete ptrToObject; 
assert(ptrToObject); 
ptrToObject = nullptr; 
assert(!ptrToObject); 

Ze względu na to, jak długo Pisałem te IFS w ten sposób, że jest drugą naturą w tym momencie, aby sprawdzić, czy wskaźniki ważne przed zastosowaniem wpisując if (obiekt *), a następnie wywołanie to członkowie.

nr Należy zachować odpowiedni wykres obiektów (korzystnie z niepowtarzalnych/inteligentnych wskaźników). Jak wskazano, nie ma sposobu, aby ustalić, czy wskaźnik, który nie jest nullptr wskazuje na prawidłowy obiekt, czy nie. Zobowiązanie należy do ciebie, aby utrzymać cykl życia w każdym razie. Dlatego właśnie opakowania na ołówki istnieją w pierwszej kolejności.

+0

No cóż, wiedziałem o tym. gdy pozostawione bez porównania, jeśli instrukcje sprawdzają, czy cokolwiek jest przekazywane, rozwiązuje literalnie cokolwiek poza 0. if int meh = 0, wówczas rozwiązuje ono fałsz. jednak jeśli adres powiedzieć int * jest 0x000 itp. oznacza to, że nie wskazuje na nic, a bool rozwiąże fałsz. jeśli wskazuje gdzieś, to nie jest zero, a następnie rozwiązuje prawdę. ale co, jeśli usuniesz obiekt ze wskaźnika? ptr stil zawiera adres taki jak 0x81A3 lub coś takiego, ale obiekt zniknął. nazywasz if, i to prawda, nawet jeśli nie ma tam obiektu. – FatalCatharsis

+1

, który spowodowałby błąd środowiska wykonawczego, jeśli zapomnisz wyzerować wskaźnik. ale jeśli wskaźnik został niejawnie porównany z nullptr, to wtedy wskaźnik byłby 0 lub zaadresowany do czegoś, to rozwiązałby wartość false, gdy obiekt nie był tam. – FatalCatharsis

+2

Tak. Więc jakie jest twoje pytanie? – dcow

6

Nie można sprawdzić, czy wskaźnik wskazuje na prawidłowy obiekt, czy nie. Jeśli wskaźnik nie jest pusty, ale nie wskazuje na poprawny obiekt, użycie wskaźnika powoduje niezdefiniowane zachowanie. Aby uniknąć tego rodzaju błędów, należy zachować ostrożność w odniesieniu do czasu życia wskazanych przedmiotów; a klasy inteligentnego wskaźnika pomagają w tym zadaniu.

Jeśli meh jest surowy wskaźnik to nie ma żadnej różnicy między if (meh) i if (meh != 0) i if (meh != nullptr). Wszystkie one kontynuują iff wskaźnik nie jest pusty.

Istnieje niejawna konwersja z literalnego 0 do nullptr.

Powiązane problemy