Posso usar if (pointer) em vez de if (ponteiro! = NULL)?

É seguro para verificar um ponteiro para não ser NULL , escrevendo simplesmente if(pointer) ou eu tenho que usar if(pointer != NULL) ?

Você pode; O ponteiro nulo é implicitamente convertido em falso booleano, enquanto os pointers não nulos são convertidos em verdadeiro. Do padrão C ++ 11, seção sobre conversões booleanas:

Um valor de referência aritmético, sem enumeração, ponteiro ou ponteiro para o tipo de membro pode ser convertido em um valor de produto do tipo bool . Um valor zero, valor de ponteiro nulo ou valor de ponteiro de membro nulo é convertido em false ; qualquer outro valor é convertido para true . Um prvalue do tipo std::nullptr_t pode ser convertido em um valor de produto do tipo bool ; o valor resultante é false .

Sim você pode.

  • Um ponteiro nulo é convertido em falso implicitamente
  • um ponteiro não nulo é convertido em verdadeiro.

Isso faz parte da conversão padrão C ++, que se encheckbox na cláusula de conversão booleana :

§ 4.12 Conversões booleanas

Um valor de referência aritmético, sem enumeração, ponteiro ou ponteiro para o tipo de membro pode ser convertido em um valor de produto do tipo bool. Um valor zero, valor de ponteiro nulo ou valor de ponteiro de membro nulo é convertido em falso; qualquer outro valor é convertido para true. Um prvalue do tipo std :: nullptr_t pode ser convertido em um valor de produto do tipo bool; o valor resultante é falso.

Sim você pode. Na verdade, eu prefiro usar if(pointer) porque é mais simples de ler e escrever quando você se acostuma.

Observe também que o C ++ 11 introduziu nullptr que é preferencial em relação a NULL .

A pergunta é respondida, mas gostaria de acrescentar meus pontos.

Eu sempre preferirei if(pointer) vez de if(pointer != NULL) e if(!pointer) vez de if(pointer == NULL) :

  • É simples, pequeno
  • Menos chances de escrever um código com bugs, suponha que se eu digitasse incorretamente o operador de verificação de igualdade == com =
    if(pointer == NULL) pode ser escrito incorretamente if(pointer = NULL) Então, vou evitá-lo, melhor é apenas if(pointer) .
    (Eu também sugeri alguma condição de Yoda em uma resposta , mas isso é assunto diferente)

  • Similarmente para while (node != NULL && node->data == key) , vou simplesmente escrever while (node && node->data == key) que é mais óbvio para mim (mostra que usando short-circuit).

  • (pode ser motivo estúpido) Porque NULL é uma macro, se alguém quiser redefinir por engano com outro valor.

Sim você pode. A capacidade de comparar valores a zeros implicitamente foi herdada de C e existe em todas as versões do C ++. Você também pode usar if (!pointer) para verificar pointers para NULL.

A verificação explícita de NULL pode fornecer uma dica para o compilador sobre o que você está tentando fazer, o que leva a ser menos propenso a erros.

insira a descrição da imagem aqui

Os casos de uso relevantes para pointers nulos são

  • Redirecionamento para algo como um nó de tree mais profundo, que pode não existir ou ainda não foi vinculado. Isso é algo que você deve sempre manter estreitamente encapsulado em uma aula dedicada, então legibilidade ou concisão não é um grande problema aqui.
  • Elencos dynamics. Encaminhar um ponteiro de class base para um determinado de class derivada (algo que você deve tentar novamente, mas que às vezes pode achar necessário) sempre tem êxito, mas resulta em um ponteiro nulo se a class derivada não corresponder. Uma maneira de verificar isso é

     Derived* derived_ptr = dynamic_cast(base_ptr); if(derived_ptr != nullptr) { ... } 

    (ou, preferencialmente, auto derived_ptr = ... ). Agora, isso é ruim, porque deixa o ponteiro derivado (possivelmente inválido, ou seja, nulo) fora da proteção de segurança if o escopo do bloco. Isso não é necessário, pois o C ++ permite que você introduza variables ​​convertíveis booleanas dentro de uma if if :

     if(auto derived_ptr = dynamic_cast(base_ptr)) { ... } 

    que não é apenas mais curto e seguro quanto ao escopo, também é muito mais claro em sua intenção: quando você verifica nulo em uma condição if separada, o leitor se pergunta “ok, então o derived_ptr não deve ser nulo aqui … bem, por que seria nulo? Considerando que a versão de uma linha diz muito claramente “se você pode base_ptr com segurança base_ptr para Derived* , então use-o para …”.

    O mesmo funciona tão bem para qualquer outra operação de falha possível que retorna um ponteiro, embora o IMO geralmente evite isso: é melhor usar algo como boost::optional como o “contêiner” para resultados de possíveis falhas de operações, em vez de pointers.

Então, se o principal caso de uso para pointers nulos sempre deve ser escrito em uma variação do estilo implícito, eu diria que é bom por razões de consistência usar sempre esse estilo, ou seja, eu defendo if(ptr) over if(ptr!=nullptr) .


Eu tenho medo de terminar com um anúncio: a syntax if(auto bla = ...) é na verdade apenas uma aproximação um pouco desajeitada para a solução real para tais problemas: correspondência de padrões . Por que você primeiro forçaria alguma ação (como lançar um ponteiro) e, em seguida, considerar que pode haver uma falha … Quero dizer, é ridículo, não é? É como se você tivesse algum alimento e quisesse fazer sopa. Você o entrega ao seu assistente com a tarefa de extrair o suco, se ele for um vegetal macio. Você não olha primeiro para isso. Quando você tem uma batata, você ainda a entrega para seu assistente, mas ela bate na sua cara com uma nota de falha. Ah, programação imperativa!

Muito melhor: considere imediatamente todos os casos que você pode encontrar. Então aja de acordo. Haskell:

 makeSoupOf :: Foodstuff -> Liquid makeSoupOf p@(Potato{..}) = mash (boil p) <> water makeSoupOf vegetable | isSoft vegetable = squeeze vegetable <> salt makeSoupOf stuff = boil (throwIn (water<>salt) stuff) 

Haskell também tem ferramentas especiais para quando há realmente uma séria possibilidade de falha (assim como para um monte de outras coisas): mônadas. Mas este não é o lugar para explicar isso.

⟩ / Advert⟩

Sim. Na verdade você deveria. Se você está se perguntando se isso cria uma falha de segmentação , isso não acontece.

sim, claro! na verdade, escrever if (ponteiro) é uma maneira mais conveniente de escrever do que se (ponteiro! = NULL) porque: 1. é fácil depurar 2. fácil de entender 3. se acidentalmente, o valor de NULL for definido, então também o código não irá falhar

Sim, você sempre pode fazer isso, pois a condição ‘IF’ só é avaliada quando a condição dentro dela é verdadeira. C não tem um tipo de retorno booleano e, portanto, retorna um valor diferente de zero quando a condição é verdadeira enquanto retorna 0 sempre que a condição em ‘IF’ for falsa. O valor diferente de zero retornado por padrão é 1. Assim, as duas formas de escrever o código estão corretas, enquanto eu sempre prefiro o segundo.

Eu acho que, como regra geral, se a sua expressão if pode ser reescrita como

 const bool local_predicate = *if-expression*; if (local_predicate) ... 

de tal forma que não provoca AVISOS, então esse deve ser o estilo preferido para a expressão if . (Eu sei que recebo avisos quando atribuo um velho C BOOL ( #define BOOL int ) a um bool C ++, e muito menos pointers.)

“É seguro..?” é uma questão sobre o padrão de linguagem e o código gerado.

“É uma boa prática?” é uma questão sobre quão bem a declaração é entendida por qualquer leitor humano arbitrário da declaração. Se você está fazendo esta pergunta, sugere que a versão “segura” é menos clara para futuros leitores e escritores.