Czy używasz NULL lub 0 (zero) dla wskaźników w C ++?

194

We wczesnych dniach C ++, kiedy był przykręcony do C, nie można było używać NULL, tak jak zostało zdefiniowane jako (void*)0. Nie można przypisać wartości NULL do żadnego wskaźnika innego niż void*, co czyni go w pewnym sensie bezużytecznym. W tamtych czasach przyjęto, że użyłeś 0(zero) wskaźników zerowych.

Do dzisiaj nadal używam zera jako wskaźnika zerowego, ale osoby wokół mnie nalegają na użycie NULL. Osobiście nie widzę żadnej korzyści z nadania nazwy ( NULL) istniejącej wartości - a ponieważ lubię także testować wskaźniki jako wartości prawdy:

if (p && !q)
  do_something();

wtedy użycie zera ma większy sens (tak jakbyś używał NULL, nie możesz logicznie używać p && !q- musisz wyraźnie porównać NULL, chyba że przyjmujesz, że NULLzero, w takim przypadku dlaczego warto użyć NULL).

Czy istnieje jakikolwiek obiektywny powód, aby preferować zero niż NULL (lub odwrotnie), czy też wszystkie są tylko osobistymi preferencjami?

Edycja: Powinienem dodać (i pierwotnie powiedzieć), że z RAII i wyjątkami rzadko używam wskaźników zero / NULL, ale czasami nadal ich potrzebujesz.

camh
źródło
9
czekaj, czy nie jest wymagany wskaźnik zerowy do oceny jako fałsz, niezależnie od tego, czy null jest wewnętrznie zerowy, czy nie?
Mooing Duck

Odpowiedzi:

186

Oto podejście Stroustrupa do tego: C ++ FAQ i styl i technika

W C ++ definicja NULLwynosi 0, więc istnieje tylko różnica estetyczna. Wolę unikać makr, więc używam 0. Innym problemem NULLjest to, że ludzie czasami mylnie wierzą, że różni się od 0 i / lub nie jest liczbą całkowitą. W kodzie wstępnie standardowym NULLbył / jest czasem definiowany jako coś nieodpowiedniego i dlatego należy / należy go unikać. To obecnie mniej powszechne.

Jeśli musisz nazwać wskaźnik zerowy, nazwij go nullptr; tak to się nazywa w C ++ 11. Wtedy nullptrbędzie słowem kluczowym.

To powiedziawszy, nie przejmuj się małymi rzeczami.

Martin Cote
źródło
7
Bjarne napisał to, zanim C ++ 0x zaczął pracować nad nowym typem zerowym. Będzie tak, że NULL będzie użyty dla tego typu, gdy będzie dostępny dla platformy, i myślę, że zobaczysz zmianę C w ogólnym konsensusie w tej sprawie.
Richard Corden,
122

Istnieje kilka argumentów (z których jeden jest stosunkowo nowy), które moim zdaniem są sprzeczne ze stanowiskiem Bjarne'a w tej sprawie.

  1. Dokumentacja zamiaru

Użycie NULLpozwala na wyszukiwanie jego użycia, a także podkreśla, że ​​deweloper chciał użyć NULLwskaźnika, niezależnie od tego, czy jest on interpretowany przez kompilator, NULLczy nie.

  1. Przeciążenie wskaźnika i „int” jest stosunkowo rzadkie

Przykład, który wszyscy cytują to:

void foo(int*);
void foo (int);

void bar() {
  foo (NULL);  // Calls 'foo(int)'
}

Jednak przynajmniej moim zdaniem problem z powyższym nie polega na tym, że używamy NULL dla stałej wskaźnika zerowego, ale na tym, że mamy przeciążenia „foo”, które przyjmują bardzo różne rodzaje argumentów. Parametr musi być intrównież, ponieważ jakikolwiek inny typ spowoduje niejednoznaczne wywołanie i wygeneruje pomocne ostrzeżenie kompilatora.

  1. Narzędzia analityczne mogą pomóc DZIŚ!

Nawet przy braku C ++ 0x dostępne są dziś narzędzia, które sprawdzają, czy NULLsą używane dla wskaźników i czy 0są używane dla typów integralnych.

  1. C ++ 11 będzie miał nowy std::nullptr_ttyp.

To najnowszy argument w tabeli. Problem 0i NULLjest aktywnie rozwiązywany dla C ++ 0x, i możesz zagwarantować, że dla każdej implementacji, która zapewnia NULL, pierwszą rzeczą, którą zrobią, jest:

#define NULL  nullptr

Dla tych, którzy używają NULLzamiast 0zmiana będzie poprawa bezpieczeństwa typu z małym lub bez wysiłku - jeśli coś może również złapać kilka błędów gdzie oni wykorzystywane NULLdo 0. Dla każdego, kto używa 0dzisiaj ... eee ... mam nadzieję, że mają dobrą znajomość wyrażeń regularnych ...

Richard Corden
źródło
1
Muszę przyznać, że są to raczej dobre punkty. Cieszę się, że C ++ 0x będzie miał typ zerowy, myślę, że dzięki temu wiele rzeczy będzie czystszych.
Rob
2
@Richard, dlaczego nie zrobić odwrotnie? Możesz użyć Meyersa nullptr_t, a następnie gdy 0x stanie się dostępne, usuń #includei zachowaj bezpieczeństwo przez całą drogę.
fnieto - Fernando Nieto
15
#define NULL nullptrwydaje się niebezpieczne. Na lepsze lub gorsze, wiele starszych kodów używa wartości NULL dla rzeczy innych niż 0. Na przykład uchwyty są często implementowane jako integralny typ, a ustawienie ich na NULLnie jest rzadkie. Widziałem nawet nadużycia, takie jak NULLustawianie charna zero-terminator.
Adrian McCarthy
8
@AdrianMcCarthy: Powiedziałbym, że byłoby niebezpieczne, gdyby istniało niebezpieczeństwo, że kod po cichu się skompiluje i będzie miał inne znaczenie. Jestem prawie pewien, że tak nie jest, więc w rzeczywistości wykryte zostaną wszystkie nieprawidłowe zastosowania NULL.
Richard Corden
3
@RichardCorden: Um, który zakłada, że ​​te inne zastosowania NULLsą w rzeczywistości nieprawidłowe. Wiele interfejsów API od dawna jest używanych NULLz uchwytami, a tak naprawdę jest to udokumentowane użycie wielu z nich. Nagłe ich złamanie i stwierdzenie, że robią to źle, nie jest pragmatyczne.
Adrian McCarthy
45

Użyj NULL. NULL pokazuje twoje zamiary. To, że wynosi 0, jest szczegółem implementacji, który nie powinien mieć znaczenia.

Andy Lester
źródło
28
0 nie jest szczegółem implementacji. Standard definiuje 0 jako dowolny wzór bitowy reprezentujący wskaźnik zerowy.
Ferruccio,
5
Jak gdyby ..!! Koleś, C ++ to język niskiego poziomu! Użyj 0, to dobrze znany idiom.
hasen
8
Rozumiem, że jest to część standardu. Jest to szczegół implementacji w zakresie odczytu kodu. Czytelnik powinien pomyśleć „wskaźnik NULL”, a nie „0, co w tym przypadku oznacza wskaźnik NULL, a nie liczbę, z którą mógłbym robić arytmetykę”.
Andy Lester
2
+1. Zgodził się z Andym. @Ferruccio, Szczegół implementacji pomysłu programisty nie jest taki sam, jak zdefiniowana
użytkownik
jeśli użyjesz NULL, w zwykłym kodzie bez złożonego nagłówka, zobaczysz błąd „NULL nie jest zdefiniowany w tym zakresie”.
Sztuczna
38

Zawsze używam:

  • NULL dla wskaźników
  • '\0' dla znaków
  • 0.0 dla pływaków i debli

gdzie 0 byłoby dobrze. Jest to kwestia zamiaru sygnalizowania. To powiedziawszy, nie jestem analny na ten temat.

Andrew Stein
źródło
25
Prawdopodobnie powinieneś użyć 0.0F dla liczb zmiennoprzecinkowych, aby uniknąć niejawnego rzutowania typu
EvilTeach
35

Już dawno przestałem używać NULL na korzyść 0 (jak również większości innych makr). Zrobiłem to nie tylko dlatego, że chciałem jak najbardziej unikać makr, ale także dlatego, że NULL wydaje się być nadmiernie używany w kodzie C i C ++. Wydaje się, że jest używany, gdy potrzebna jest wartość 0, nie tylko dla wskaźników.

W nowych projektach umieszczam to w nagłówku projektu:

static const int nullptr = 0;

Teraz, gdy pojawią się kompilatory zgodne z C ++ 0x, wszystko, co muszę zrobić, to usunąć tę linię. Zaletą tego jest to, że Visual Studio rozpoznaje nullptr jako słowo kluczowe i odpowiednio je wyróżnia.

Ferruccio
źródło
4
Używanie NULL będzie bardziej przenośne na dłuższą metę. „nullptr” będzie dostępny dla niektórych platform, a nie dla innych. Twoje rozwiązanie wymaga użycia preprocesora wokół deklaracji, aby upewnić się, że jest obecna tylko wtedy, gdy jest to wymagane. NULL zrobi to automatycznie.
Richard Corden,
6
Nie zgadzam się. W krótkim okresie będzie mniej przenośny, dopóki kompilatory nie nadążą. W dłuższej perspektywie będzie równie przenośny i może trochę bardziej czytelny.
Ferruccio,
4
Ponadto zawsze możesz # zdefiniować nullptr NULL dla swojego kompilatora innego niż C ++ 0x1.
Anteru,
20
    cerr << sizeof(0) << endl;
    cerr << sizeof(NULL) << endl;
    cerr << sizeof(void*) << endl;

    ============
    On a 64-bit gcc RHEL platform you get:
    4
    8
    8
    ================

Morał tej historii. Powinieneś używać NULL, kiedy masz do czynienia ze wskaźnikami.

1) Deklaruje twój zamiar (nie zmuszaj mnie do przeszukiwania całego twojego kodu, próbując dowiedzieć się, czy zmienna jest wskaźnikiem, czy jakimś typem liczbowym).

2) W niektórych wywołaniach API, które oczekują zmiennych argumentów, użyją wskaźnika NULL do wskazania końca listy argumentów. W takim przypadku użycie „0” zamiast NULL może powodować problemy. Na platformie 64-bitowej wywołanie va_arg potrzebuje 64-bitowego wskaźnika, a jednak przekażesz tylko 32-bitową liczbę całkowitą. Wydaje mi się, że polegasz na pozostałych 32-bitach, które zostaną dla ciebie wyzerowane? Widziałem niektóre kompilatory (np. Icpc Intela), które nie są tak łaskawe - co spowodowało błędy w czasie wykonywania.

abonet
źródło
NULLbyć może nie jest przenośny i nie jest bezpieczny. Mogą istnieć platformy, które nadal #define NULL 0(zgodnie z często zadawanymi pytaniami Stroustrup: Czy powinienem używać NULL lub 0? Cytowanych w głównym pytaniu i jest to jeden z pierwszych wyników wyszukiwania). Przynajmniej w starszym C ++ 0ma specjalne znaczenie pojęciowe w kontekście wskaźnika. Nie powinieneś konkretnie myśleć o bitach. Należy również pamiętać, że w różnych kontekstach Integer ( short, int, long long) „ sizeof(0)” będzie inna. Myślę, że ta odpowiedź jest nieco myląca.
FooF,
(Osobiście jako programista C w codziennym życiu, przyszedł odwiedzić to pytanie, aby zrozumieć, dlaczego ludzie chcą używać NULLzamiast (char *)0, (const char *)0albo (struct Boo *)0albo (void *)0albo cokolwiek się wyraża zamiar jaśniej. - bez (moim zdaniem) zbyt uciążliwe)
FOOF
Głosować. dzieje się to w kompilatorze msvc2013 C. w wersji 64-bitowej, 0 po konwersji na wskaźnik nie gwarantuje, że będzie NULL Pointer.
pengMiao,
16

Jeśli dobrze pamiętam, NULL jest inaczej zdefiniowany w nagłówkach, których użyłem. Dla C jest zdefiniowany jako (void *) 0, a dla C ++ jest zdefiniowany jako tylko 0. Kod wyglądał mniej więcej tak:

#ifndef __cplusplus
#define NULL (void*)0
#else
#define NULL 0
#endif

Osobiście nadal używam wartości NULL do reprezentowania zerowych wskaźników, co wyraźnie wskazuje, że używasz wskaźnika zamiast jakiegoś integralnego typu. Tak wewnętrznie wartość NULL wynosi wciąż 0, ale nie jest reprezentowana jako taka.

Ponadto nie polegam na automatycznej konwersji liczb całkowitych na wartości logiczne, ale wyraźnie je porównuję.

Na przykład wolisz używać:

if (pointer_value != NULL || integer_value == 0)

zamiast:

if (pointer_value || !integer_value)

Wystarczy powiedzieć, że to wszystko naprawiono w C ++ 11, w którym można po prostu użyć nullptrzamiast NULL, a także nullptr_ttaki jest typ nullptr.

Daemin
źródło
15

Powiedziałbym, że historia przemówiła, a ci, którzy opowiadali się za użyciem 0 (zero), byli w błędzie (w tym Bjarne Stroustrup). Argumenty na korzyść 0 to głównie estetyka i „osobiste preferencje”.

Po utworzeniu C ++ 11, z nowym typem nullptr, niektóre kompilatory zaczęły narzekać (z parametrami domyślnymi) na przekazywanie 0 do funkcji z argumentami wskaźnika, ponieważ 0 nie jest wskaźnikiem.

Jeśli kod został napisany przy użyciu wartości NULL, można było przeprowadzić proste wyszukiwanie i zamianę przez bazę kodu, aby zamiast tego był nullptr. Jeśli utkniesz w kodzie napisanym przy użyciu 0 jako wskaźnika, jego aktualizacja jest znacznie bardziej nużąca.

A jeśli musisz teraz napisać nowy kod do standardu C ++ 03 (i nie możesz używać nullptr), naprawdę powinieneś po prostu użyć NULL. Ułatwi ci to aktualizację w przyszłości.

Gaute Lindkvist
źródło
11

Zwykle używam 0. Nie lubię makr i nie ma gwarancji, że nagłówek innej firmy, którego używasz, nie redefiniuje wartości NULL jako czegoś dziwnego.

Możesz użyć obiektu nullptr zaproponowanego przez Scotta Meyersa i innych, dopóki C ++ nie otrzyma słowa kluczowego nullptr:

const // It is a const object...
class nullptr_t 
{
public:
    template<class T>
    operator T*() const // convertible to any type of null non-member pointer...
    { return 0; }

    template<class C, class T>
    operator T C::*() const   // or any type of null member pointer...
    { return 0; }

private:
    void operator&() const;  // Can't take address of nullptr

} nullptr = {};

Google „nullptr”, aby uzyskać więcej informacji.

jon-hanson
źródło
9
Każda biblioteka innej firmy, która definiuje NULL na wartość inną niż 0 (lub (void*)0jeśli jest kompilowana jako kod C), po prostu prosi o problemy i nie powinna być używana.
Adam Rosenfield,
2
Czy kiedykolwiek widziałeś bibliotekę, która redefiniuje wartość NULL? Zawsze? Gdyby taka biblioteka kiedykolwiek istniała, miałbyś większe problemy niż na nowo zdefiniowane NULL, na przykład używasz biblioteki, która jest na tyle głupia, aby na nowo zdefiniować NULL.
Andy Lester,
1
Ponad dekadę temu niejasno pamiętam, że miałem do czynienia z niektórymi nagłówkami innych firm, być może z Orbix lub ObjectStore, które definiowały NULL. Wydaje mi się, że mam patologiczną nienawiść do makr po marnowaniu kilku dni i nocy, próbując nakłonić różne nagłówki innych firm do pracy z Windows.h.
jon-hanson
2
„nie lubię makr” to dziwna krytyka obiektowego #define. Może chcesz powiedzieć, że nie lubisz preprocesora C?
Andrew Prock,
@Andrew - Wydaje mi się, że jedyną korzyścią z NULLponad (type *)0jest możliwość wyszukiwania. W przeciwnym razie wydaje się niepotrzebne zaciemnianie, jeśli nie jest to idiom C. Osobiście uważam, że idiom rozprzestrzeniania się NULLpo całym miejscu zasługuje na śmierć. NULLjest moim zdaniem bezużytecznym makrem. Brzytwa Ockhama ma tu trochę roboty ...
FooF
11

Kiedyś pracowałem na maszynie, w której 0 był prawidłowym adresem, a NULL został zdefiniowany jako specjalna wartość ósemkowa. Na tym komputerze (0! = NULL), więc kod taki jak

char *p;

...

if (p) { ... }

nie działałby zgodnie z oczekiwaniami. MUSISZ napisać

if (p != NULL) { ... }

Chociaż uważam, że większość kompilatorów obecnie definiuje NULL jako 0, wciąż pamiętam lekcję sprzed lat: NULL niekoniecznie jest 0.

Mxg
źródło
26
Nie korzystałeś ze zgodnego kompilatora. Standard mówi, że NULL wynosi 0 i że kompilator powinien przekonwertować 0 w kontekście wskaźnika na prawidłową wartość NULL dla łuku.
Evan Teran,
17
Tak masz rację. Było to w połowie lat 80., zanim ANSI wyprodukowało standard C. Wówczas nie istniało coś takiego jak zgodność, a autorzy kompilatorów mieli swobodę interpretacji języka według własnego uznania. Dlatego potrzebny był standard.
MXG,
9

Myślę, że standard gwarantuje, że NULL == 0, więc możesz to zrobić. Wolę NULL, ponieważ dokumentuje twoją intencję.

Mark Ransom
źródło
Jeśli masz zagnieżdżone struktury, myślę, że powiedzenie foo.bar_ptr = (Bar *) 0wyraża intencję o wiele jaśniej niż foo.bar_ptr = NULL. Ten nawyk umożliwia także kompilatorowi wykrywanie błędów błędnych przekonań. Dla mnie foo.bar_ptr = 0wyraża intencję, a także użycie, NULLjeśli wiem, że foo.bar_ptrto wskaźnik.
FooF,
9

Użycie 0 lub NULL będzie miało taki sam efekt.

Nie oznacza to jednak, że oba są dobrymi praktykami programowania. Biorąc pod uwagę, że nie ma różnicy w wydajności, wybranie opcji niskiego poziomu świadomości zamiast agnostycznej / abstrakcyjnej alternatywy jest złą praktyką programistyczną. Pomóż czytelnikom Twojego kodu zrozumieć proces myślowy .

NULL, 0, 0,0, „\ 0”, 0x00 i whatelse tłumaczą to samo, ale są różnymi logicznymi jednostkami w twoim programie. Powinny być używane jako takie. NULL to wskaźnik, 0 to ilość, 0x0 to wartość, której bity są interesujące itp. Nie przypisalibyśmy wskaźnika „\ 0” bez względu na to, czy się kompiluje, czy nie.

Wiem, że niektóre społeczności zachęcają do wykazania się dogłębną wiedzą na temat środowiska poprzez łamanie jego umów. Odpowiedzialni programiści tworzą jednak kod, który można utrzymać i nie dopuszczają do tego.

Chris
źródło
5

Dziwne, nikt o tym nie wspominał, w tym Stroustroup. Choć dużo mówić o standardach i estetyka nikt nie zauważył, że jest to niebezpieczne w użyciu 0w NULL„s zamiast, na przykład, w liście zmiennych argumentów na architekturze gdzie sizeof(int) != sizeof(void*). Podobnie jak Stroustroup, wolę 0ze względów estetycznych, ale trzeba uważać, aby nie używać go tam, gdzie jego typ może być niejednoznaczny.

Michael Krelin - haker
źródło
I w tych niebezpiecznych miejscach nadal można używać 0pod warunkiem, że określenie, które 0masz na myśli - na przykład (int *)0, (char *)0, (const char *)0lub (void *)0lub (unsigned long long) 0lub cokolwiek. To moim zdaniem wyraża intencję o wiele jaśniej niż NULL.
FooF,
1
Jasne, jeśli nie wiesz, co NULLoznacza.
Michael Krelin - haker
Osobiście uważam, że to trochę niesmaczne, gdy niepotrzebnie rzucam coś, (void *)kiedy mogę użyć dokładnego typu. Celowo podałem przykład (zwykle) 64-bitowej liczby całkowitej na liście, ponieważ jest ona analogiczna do wielkości wskaźnika. Ponadto, jeśli moje wspomnienie, że starszy C ++ zdefiniowany NULLjako 0dokładny (minęły lata, odkąd programowałem w C ++), to nie widzimy żadnej poprawy poprawności programu. Nowszy standard C ++ na szczęście zapewnia nullptrsłowo kluczowe, dzięki czemu możemy pozbyć się tej NULLbrzydoty i całego kontrowersji pisząc nowsze C ++.
FooF,
Właśnie dlatego przesyłanie do (void*)abstrakcji zostało abstrakcyjne NULL. I NULLfaktycznie nie wyrazić intencją wyraźnie większość czasu. I myślę, że twoje wspomnienia są błędne. Nie jestem pewien co do standardów, ale w praktyce uważam, że tak było (void*)0. I tak, nullptrto niezły prettifier, choć sprowadza się do tego samego NULL- określania wskaźnika zerowego bez określania typu.
Michael Krelin - haker
1
@FooF, na niektórych platformach - może. W mojej rzeczywistości działało i dlatego podejrzewam, że zostało zdefiniowane jako wskaźnik. Jeśli chodzi o solidność, tak, to, co próbowałem powiedzieć, że używanie nullptrma ten sam przekaz NULL, co dotyczyło tylko wyrażenia zamiaru, o którym wspomniałeś na samym początku. (Wstępne przetwarzanie NULLnowoczesnych gcczbiorów __null, cokolwiek to jest).
Michael Krelin - haker
4

Staram się unikać całego pytania, w miarę możliwości korzystając z referencji C ++. Zamiast

void foo(const Bar* pBar) { ... }

często możesz pisać

void foo(const Bar& bar) { ... }

Oczywiście nie zawsze to działa; ale wskaźniki zerowe mogą być nadużywane.

.Аn
źródło
3

Jestem z Stroustrup na tym :-) Ponieważ NULL nie jest częścią języka, wolę używać 0.

Obrabować
źródło
3

Przede wszystkim preferencje osobiste, choć można by argumentować, że NULL czyni dość oczywistym, że obiekt jest wskaźnikiem, który obecnie nie wskazuje na nic, np.

void *ptr = &something;
/* lots o' code */
ptr = NULL; // more obvious that it's a pointer and not being used

IIRC, standard nie wymaga wartości NULL równej 0, więc użycie tego, co zdefiniowano w <stddef.h>, jest prawdopodobnie najlepsze dla twojego kompilatora.

Innym aspektem tego argumentu jest to, czy należy użyć porównań logicznych (niejawne rzutowanie na bool), czy sprawdzenia jawności względem wartości NULL, ale sprowadza się to również do czytelności.

Jimmy
źródło
3

Wolę używać NULL, ponieważ wyjaśnia, że ​​twoją intencją jest wartość reprezentująca wskaźnik, a nie wartość arytmetyczna. Fakt, że jest to makro, jest niefortunny, ale ponieważ jest tak głęboko zakorzeniony, nie ma niebezpieczeństwa (chyba że ktoś zrobi coś naprawdę bezczelnego). Chciałbym, żeby to było słowo kluczowe od samego początku, ale co możesz zrobić?

To powiedziawszy, nie mam problemu z używaniem wskaźników jako wartości prawdy samych w sobie. Podobnie jak w przypadku NULL, jest to zakorzeniony idiom.

C ++ 09 doda konstrukcję nullptr, która moim zdaniem jest już dawno spóźniona.

Michael Burr
źródło
1

Zawsze używam 0. Nie z żadnego naprawdę przemyślanego powodu, tylko dlatego, że kiedy uczyłem się C ++, przeczytałem coś, co zalecało użycie 0 i po prostu zawsze tak robiłem. Teoretycznie może wystąpić problem z czytelnością, ale w praktyce nigdy nie spotkałem się z takim problemem w tysiącach roboczogodzin i milionach wierszy kodu. Jak mówi Stroustrup, tak naprawdę jest to tylko osobisty problem estetyczny, dopóki standard nie stanie się zerowy.

Gerald
źródło
1

Ktoś mi kiedyś powiedział ... Przedefiniuję NULL do 69. Od tego czasu nie używam: P

To sprawia, że ​​twój kod jest dość podatny na ataki.

Edytować:

Nie wszystko w standardzie jest idealne. Makro NULL jest zdefiniowaną implementacją stałą zerowego wskaźnika C ++, który nie jest w pełni kompatybilny z makrem C NULL, co oprócz ukrywania typu przekształca go w bezużyteczne i podatne na błędy narzędzie.

NULL nie zachowuje się jak wskaźnik zerowy, ale jako literał O / OL.

Powiedz, że następny przykład nie jest mylący:

void foo(char *); 
void foo(int); 
foo(NULL); // calls int version instead of pointer version! 

Z tego powodu w nowym standardzie pojawia się std :: nullptr_t

Jeśli nie chcesz czekać na nowy standard i chcesz użyć nullptr, użyj co najmniej przyzwoitego, takiego jak zaproponowany przez Meyersa (patrz komentarz jon.h).

fnieto - Fernando Nieto
źródło
5
NULLjest dobrze zdefiniowaną częścią standardu C ++. Umożliwianie osobom, które lubią redefiniować standardowe makra edycji kodu w twoim projekcie, sprawia, że ​​Twój kod jest podatny na ataki; używanie NULLnie.
CB Bailey,
1

Cóż, argumentuję za tym, aby w ogóle nie używać wskaźników 0 lub NULL.

Korzystanie z nich prędzej czy później doprowadzi do błędów segmentacji w kodzie. Z mojego doświadczenia wynika, że ​​wskaźniki w gereral są jednym z największych źródeł błędów w C ++

prowadzi również do instrukcji „jeśli-nie-zerowe” w całym kodzie. Znacznie ładniej, jeśli możesz polegać na zawsze poprawnym stanie.

Prawie zawsze istnieje lepsza alternatywa.

Jan P.
źródło
2
Gwarantowana awaria segmentacji (i jest gwarantowana w nowoczesnych systemach, gdy dereferencja 0) jest przydatna do debugowania. O wiele lepsze niż dereferencje losowych śmieci i zdobywanie informacji, kto wie, jaki wynik.
Wyścigi lekkości na orbicie
-4

Ustawienie wskaźnika na 0 nie jest po prostu takie jasne. Zwłaszcza jeśli korzystasz z języka innego niż C ++. Dotyczy to zarówno C, jak i Javascript.

Niedawno dodałem trochę kodu:

virtual void DrawTo(BITMAP *buffer) =0;

dla czystej funkcji wirtualnej po raz pierwszy. Przez tydzień myślałem, że to jakiś magiczny jiberjash. Kiedy zdałem sobie sprawę, że po prostu ustawiałem wskaźnik funkcji na null(ponieważ funkcje wirtualne są w większości przypadków wskaźnikami funkcji dla C ++), kopnąłem się.

virtual void DrawTo(BITMAP *buffer) =null;

byłby mniej mylący niż to basterdation bez odpowiedniego odstępu od moich nowych oczu. Właściwie zastanawiam się, dlaczego C ++ nie używa małych liter, nulltak jak teraz używa małych i fałszywych i prawdziwych.

Pizzach
źródło
Ogólnie wolę NULl od 0 dla wskaźników. Jednak „= 0;” jest idiomatycznym sposobem zadeklarowania czystej funkcji wirtualnej w C ++. Zdecydowanie odradzam używanie „= NULL;” w tym konkretnym przypadku.
danio
To jest najśmieszniejszy komentarz na temat StackOverflow. Prawdopodobnie już wiesz, że podany przykład jest składnią czystej funkcji wirtualnej, a nie wskaźnikiem. I tak @danio ma rację, nie powinieneś używać NULL dla czystej funkcji wirtualnej.
sgowd