Devo eseguire il confronto con NULL o nullptr?

5

Diciamo che ho una funzione C ++ simile a questa:

bool Foo(Bar* b)
{
    if(b == nullptr) {
        return false; 
    }
    // Do stuff
    return true;
}

Diciamo inoltre che, a causa delle limitazioni con alcuni degli strumenti che non supportano nessuno standard più recente di C ++ 03, ho questo codice in un'intestazione:

#if __cplusplus <= 199711L
    #define nullptr (0)
    #include <stdint.h>
#else
    #include <cstdint>
#endif // End if C++03

Il mio compilatore lo costruirà senza avvertimenti o errori. So che non ho per lanciare nullptr ma c'è una ragione convincente che io dovrebbe farlo? Cioè, c'è il potenziale per alcuni bug di insinuarsi in relazione a Foo() che usando if (b == static_cast<Bar*>(nullptr)) avrebbe evitato e che il compilatore non mi avrebbe avvertito riguardo (in entrambi i C + +03 o C ++ 11 o successivo)?

Le mie ragioni per evitare il cast sarebbero:

  1. L'aggiunta del cast a ogni utilizzo di nullptr sembra che renderebbe il codice più disordinato / più difficile da leggere.
  2. Non ho visto molto (se esiste) il codice che lo fa.

Il numero 2 non è un buon motivo in sé e per sé, quindi mi chiedo se è fatto perché è più conveniente per l'autore del codice e / o se è perché non c'è davvero una ragione convincente per farlo.

Modifica in base alla risposta proposta: Le domande sono:

  1. Se sono bloccato con C ++ 03 ora, ma voglio ancora pianificare il C ++ 11 in futuro, è la migliore opzione per restare con il% co_de legacy impostato su un valore intero e tutto il meglio- pratiche che vengono con esso?
  2. Se sono bloccato con qualcosa della varietà NULL , dovrei sempre applicare un cast? Ad esempio: #define NULL (0) non è qualcosa che vedo fatto molto e mi chiedo se questo è per pigrizia o se ci sono buone ragioni per farlo o non farlo nel caso di confronti (come i controlli dei puntatori nulli esemplificati sopra) .
posta CodingHero 12.12.2017 - 16:43
fonte

1 risposta

19

Let's further say that, because of limitations with some of the tools I have that don't support any standards newer than C++03, I have this code in a header:

Questa è una pessima idea.

L'espressione (0) è (più o meno) equivalente alla definizione C ++ di NULL . Il fatto è che nullptr è stato inventato specificamente per far fronte alle carenze del NULL .

Quindi, fingere di essere in qualche modo equivalenti, confonderà solo i lettori. Renderà le persone abituate al codice di scrittura C ++ 11 che ha un comportamento diverso quando compilato su compilatori C ++ 03. Ad esempio:

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

foo(nullptr);

C ++ 11 ci dice che questo deve chiamare foo(Bar*) . Ma la tua macro C ++ 03 chiamerà invece foo(int) . Poiché foo(NULL) causerebbe lo stesso problema, nullptr è stato inventato per fermarlo.

Quindi avere un codice C ++ 03 che assomiglia al codice C ++ 11 ma si comporta in modo diverso è una pessima idea.

nullptr , in base alla progettazione, praticamente non è mai necessario eseguire il cast su un tipo di puntatore specifico. L'unica eccezione è se chiami un qualche tipo di funzione del modulo:

template<typename T>
void foo(T* p);

Ma anche in questo caso, puoi utilizzare foo<ActualType>(nullptr) e ottenere lo stesso effetto di foo(static_cast<ActualType*>(nullptr)) .

Il tuo non- nullptr ha bisogno di essere lanciato nelle stesse circostanze in cui fa NULL . Infatti, poiché è essenzialmente equivalente a NULL , dovresti semplicemente usare NULL . E quindi, hai tutti gli avvertimenti che NULL ha.

E FYI: è praticamente impossibile creare un tipo in C ++ 03 che abbia un comportamento identico al tipo nullptr_t di C ++ 11. Puoi avvicinarti, usando le conversioni implicite e così via. Ma ci saranno sempre casi d'angolo in cui non funziona.

Quindi smetti di promettere il nullptr di comportamento che non puoi garantire.

    
risposta data 12.12.2017 - 17:49
fonte

Leggi altre domande sui tag