É seguro verificar se um ponteiro não está NULL
escrevendo de forma simples if(pointer)
ou preciso usar if(pointer != NULL)
?
c++
pointers
if-statement
null
null-pointer
danijar
fonte
fonte
0
ounullptr
. (NULL
É um C'ism, e requer incluindo um arquivo de cabeçalho.)NULL
C ++ a partir daqui porqueNULL
é uma macro dependente de implementação que pode fornecer comportamentos ambíguos.Respostas:
Você pode; o ponteiro nulo é implicitamente convertido em booleano false, enquanto ponteiros não nulos são convertidos em true. No padrão C ++ 11, seção Conversões Booleanas:
fonte
Sim você pode.
Isso faz parte da conversão padrão do C ++, que se enquadra na cláusula de conversão booleana :
§ 4.12 Conversões booleanas
fonte
Sim você pode. Na verdade, eu prefiro usar
if(pointer)
porque é mais fácil ler e escrever quando você se acostumar.Observe também que o C ++ 11 introduziu o
nullptr
que é preferívelNULL
.fonte
if(som_integer)
vsif(some_integer != 0)
porque números inteiros também não são booleanos, certo? Eu prefiro evitar0
ouNULL
em uma declaração if.if (pointer)
me preferir , mas meif (ptr != nullptr)
parece perfeitamente legítimo. Por outro lado, se eu visse alguém da minha equipe que escrevesse,if (some_integer)
eu os faria mudar paraif (some_integer != 0)
. No entanto, não vou fingir que não é uma preferência relativamente arbitrária da minha parte - simplesmente prefiro não tratar ponteiros e números inteiros da mesma forma.if(isReady)
if(filePtr)
if(serviceNo)
? Criar nomes de variáveis incorretos de propósito não significa muito neste caso. Enfim, eu já entendi seu ponto de vista e entendi, mas posso insistir em usar meu próprio estilo de codificação, ok?A pergunta foi respondida, mas eu gostaria de acrescentar meus pontos.
Eu vou sempre preferir
if(pointer)
, em vez deif(pointer != NULL)
eif(!pointer)
em vez deif(pointer == NULL)
:Menos chances de escrever um código de buggy, que se eu grafada operador cheque igualdade
==
com=
if(pointer == NULL)
pode ser grafadaif(pointer = NULL)
Então eu vou evitá-lo, o melhor é apenasif(pointer)
.(Eu também sugeri alguma condição Yoda em uma resposta , mas isso é uma questão diferente)
Da mesma forma
while (node != NULL && node->data == key)
, escreverei owhile (node && node->data == key)
que é mais óbvio para mim (mostra que usando curto-circuito).fonte
(boolean expression)? true : false
é completamente inútil. A expressão avalia paratrue
ou parafalse
; o que você diz é "se é verdade, me dê verdadeira, se for falsa, me dê falsa". Resumindo: é completamente equivalente à própria expressão booleana. Observe quenode == NULL
é uma expressão booleana. BTW, suas duas implementações retornam exatamente o oposto uma da outra. Ou você quer!=
no primeiro, ou apenas um!
no segundo.=
vez de,==
é fazer suas variáveisconst
sempre que possível. Por exemplo, você pode definir sua função comoisEmnpy(node* const head) { ... }
e, em seguida, o compilador se recusaria a compilá-la se você escrevesse acidentalmente emnode = NULL
vez denode == NULL
. Claro que isso funciona apenas para variáveis que você realmente não precisa alterar.T* get() const
vez deoperator T*() const
evitar conversões implícitas. No entanto, eles têm umoperator bool() const
.A verificação explícita de NULL pode fornecer uma dica ao compilador sobre o que você está tentando fazer, o que leva a ser menos propenso a erros.
fonte
Sim você pode. A capacidade de comparar valores com zeros implicitamente foi herdada de C e existe em todas as versões do C ++. Você também pode usar
if (!pointer)
para verificar os ponteiros quanto a NULL.fonte
Os casos de uso relevantes para ponteiros nulos são
Moldes dinâmicos. A conversão de um ponteiro de classe base para um de classe derivada específico (algo que você deve tentar novamente evitar, mas às vezes pode achar necessário) sempre é bem-sucedida, mas resulta em um ponteiro nulo se a classe derivada não corresponder. Uma maneira de verificar isso é
(ou, de preferência,
auto derived_ptr = ...
). Agora, isso é ruim, porque deixa o ponteiro derivado (possivelmente inválido, ou seja, nulo) foraif
do escopo do bloco de proteção . Isso não é necessário, pois o C ++ permite introduzir variáveis conversíveis em booleano dentro de umaif
condição- :que não é apenas mais curto e seguro para o 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
derived_ptr
não deve ser nulo aqui ... bem, por que ser nulo? " Considerando que a versão de uma linha diz muito claramente "se você pode transmitirbase_ptr
com segurançaDerived*
, então use-o para ...".O mesmo funciona da mesma forma 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
o "contêiner" para resultados de possíveis operações com falha, em vez de ponteiros.Assim, se o caso de uso principal para ponteiros nulos deve sempre ser escrito em uma variação do-cast-style implícita, eu diria que é bom por razões de coerência para sempre usar este estilo, ou seja, eu defendo para
if(ptr)
cimaif(ptr!=nullptr)
.Receio ter que terminar com um anúncio: a
if(auto bla = ...)
sintaxe é, na verdade, apenas uma aproximação um pouco complicada da solução real para esses problemas: correspondência de padrões . Por que você primeiro força alguma ação (como lançar um ponteiro) e depois considera que pode haver uma falha ... Quero dizer, é ridículo, não é? É como, você tem alguns alimentos e quer fazer sopa. Você o entrega ao assistente com a tarefa de extrair o suco, se for um vegetal macio. Você não olha primeiro para isso. Quando você tem uma batata, ainda a entrega ao seu assistente, mas ele a devolve ao seu rosto 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:
Haskell também tem ferramentas especiais para quando há realmente uma possibilidade séria de falha (assim como para várias outras coisas): mônadas. Mas este não é o lugar para explicar isso.
⟨/advertir⟩
fonte
if(ptr)
e nãoif(ptr != nullptr)
, as quais há muito mais a dizer.sim, claro! de fato, escrever se (ponteiro) é uma maneira mais conveniente de escrever do que se (ponteiro! = NULL) porque: 1. é fácil depurar 2. fácil entender 3. se, acidentalmente, o valor de NULL for definido, então também o código não trava
fonte
Sim. Na verdade você deveria. Se você está se perguntando se isso cria uma falha de segmentação , isso não ocorre.
fonte
Como outros já responderam bem, ambos são intercambiáveis.
No entanto, vale ressaltar que pode haver um caso em que você queira usar a declaração explícita, ie
pointer != NULL
.Consulte também https://stackoverflow.com/a/60891279/2463963
fonte
Sim, você sempre pode fazer isso como a condição 'SE' avalia apenas quando a condição interna se torna verdadeira. C não possui 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. Portanto, as duas maneiras de escrever o código estão corretas, enquanto eu sempre preferirei o segundo.
fonte
Eu acho que, como regra geral, se sua expressão if puder ser reescrita como
de forma que não cause AVISOS, esse deve ser o estilo preferido para a expressão if . (Eu sei que recebo avisos quando atribuo um C
BOOL
(#define BOOL int
) antigo a um C ++bool
, sem falar em indicadores.)fonte
"É seguro..?" é uma pergunta sobre o padrão de idioma e o código gerado.
"É uma boa prática?" é uma pergunta sobre quão bem a declaração é entendida por qualquer leitor humano arbitrário da declaração. Se você está fazendo essa pergunta, sugere que a versão "segura" é menos clara para futuros leitores e escritores.
fonte