Pergunta

Nos primeiros dias de C ++ quando foi aparafusadas em cima de C, você não poderia usar NULL como foi definida como (void*)0. Você não poderia atribuir NULL a qualquer ponteiro que não void*, o que tornou tipo de inútil. Naqueles dias, aceitou-se que você usou 0 (zero) para ponteiros nulos.

Para este dia, eu continuei a utilização de zero como um ponteiro nulo, mas os que me rodeiam insistir em usar NULL. Eu pessoalmente não vejo qualquer benefício para dar um nome (NULL) para um valor existente - e desde que eu também gostaria de ponteiros de teste como valores de verdade:

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

em seguida, usando de zero faz mais sentido (como em se utilizar NULL, você não pode logicamente usar p && !q - você precisa comparar explicitamente contra NULL, a menos que você assumir NULL é zero, caso em que por utilização NULL).

Existe alguma razão objectiva para preferem zero ao longo NULL (ou vice-versa), ou é tudo preferência apenas pessoal?

Edit:. Devo acrescentar (e quis dizer originalmente) que, com RAII e exceções, eu raramente uso de zero ponteiros / null, mas às vezes você precisa deles ainda

Foi útil?

Solução

Está aqui a tomada de Stroustrup sobre isso: C ++ estilo e técnica FAQ

Em C ++, a definição de NULL é 0, então existe apenas uma diferença estética. Eu prefiro evitar macros, então eu uso 0. Outro problema com NULL é que as pessoas às vezes erroneamente acreditam que ele é diferente de 0 e / ou não um inteiro. No código pré-padrão, NULL foi / é muitas vezes definido como algo inadequado e, portanto, tinha / tem que ser evitado. Isso é menos comum nos dias de hoje.

Se você tem que nomear o ponteiro nulo, chamá-lo nullptr; isso é o que é chamado em C ++ 11. Então, nullptr será uma palavra-chave.

Dito isto, não suar as pequenas coisas.

Outras dicas

Existem alguns argumentos (um dos quais é relativamente recente) que eu acredito posição contradizem do Bjarne sobre isso.

  1. Documentação de intenções

Usando NULL permite pesquisas sobre seu uso, e ele também destaca que o desenvolvedor queria para usar um ponteiro NULL, independentemente de ele está sendo interpretado pelo compilador como NULL ou não.

  1. Sobrecarga de ponteiro e 'int' é relativamente rara

O exemplo que cita todos é:

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

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

No entanto, pelo menos na minha opinião, o problema com o acima não é que estamos usando NULL para a constante ponteiro nulo, é que temos sobrecargas de 'foo', que leva muito diferentes tipos de argumentos. O parâmetro deve ser um int também, como qualquer outro tipo resultará em uma chamada ambígua e assim gerar um aviso do compilador útil.

  1. Ferramentas de análise pode ajudar HOJE!

Mesmo na ausência de C ++ 0x, existem ferramentas disponíveis hoje que verificar se NULL está sendo usado para ponteiros, e que 0 está sendo usado para tipos integrais.

  1. C ++ 11 terá um novo tipo std::nullptr_t.

Este é o mais novo argumento para a mesa. O problema da 0 e NULL está sendo tratado ativamente para C ++ 0x, e você pode garantir que para cada aplicação que fornece NULL, a primeira coisa que eles vão fazer é:

#define NULL  nullptr

Para aqueles que usam NULL em vez de 0, a mudança será uma melhoria no tipo de segurança com pouco ou nenhum esforço - se alguma coisa ele também pode pegar alguns bugs onde eles NULL utilizado para 0. Para qualquer um usando 0 hoje .... erm ... bem espero que eles têm um bom conhecimento de expressões regulares ...

Use NULL. NULL mostra sua intenção. Que é 0 é um detalhe de implementação que não deve importar.

Eu parei de usar NULL em favor de 0 há muito tempo (assim como a maioria dos outros macros). Eu fiz isso, não só porque eu queria evitar macros, tanto quanto possível, mas também porque NULL parece ter se tornado mais utilizado em código C e C ++. Parece ser usado sempre que é necessário um valor 0, não apenas para os ponteiros.

Em novos projetos, eu coloquei isso em um cabeçalho de projeto:

static const int nullptr = 0;

Agora, quando C ++ 0x compiladores compatíveis chegar, tudo o que tenho a fazer é remover essa linha. Uma boa vantagem disto é que o Visual Studio já reconhece nullptr como palavra-chave e destaca-lo adequadamente.

Eu sempre uso:

  • NULL para ponteiros
  • '\0' para chars
  • 0.0 para carros alegóricos e duplas

onde 0 faria muito bem. É uma questão de sinalização intenção. Dito isto, eu não sou anal sobre isso.

    cerr << sizeof(0) << endl;
    cerr << sizeof(NULL) << endl;
    cerr << sizeof(void*) << endl;

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

A moral da história. Você deve usar NULL Quando você está lidando com ponteiros.

1) Declara a sua intenção (não me faça pesquisar através de todo o seu código tentando descobrir se uma variável é um ponteiro ou algum tipo numérico).

2) Em certas chamadas de API que esperam argumentos variáveis, eles vão usar um NULL-pointer para indicar o final da lista de argumentos. Neste caso, usando um '0', em vez de NULL pode causar problemas. Em uma plataforma de 64 bits, a chamada va_arg quer um ponteiro de 64 bits, mas você vai estar passando apenas uma inteiro de 32 bits. Parece-me que você está contando com os outros 32 bits a ser zerado para você? Eu vi alguns compiladores (por exemplo ICPC da Intel), que não são tão gracioso -. E isso resultou em erros de execução

Se bem me lembro NULL é definido de forma diferente nos cabeçalhos que eu usei. Para C é definido como (* void) 0, e para C ++ de TI define como apenas 0. O código parecia algo como:

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

Pessoalmente eu ainda utilizar o valor NULL para representar ponteiros nulos, torna-se explícito que você está usando um ponteiro em vez de algum tipo integral. Sim internamente o valor NULL ainda é 0, mas não é representado como tal.

Além disso eu não contar com a conversão automática de números inteiros para valores booleanos, mas explicitamente compará-los.

Por exemplo preferem usar:

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

em vez de:

if (pointer_value || !integer_value)

Basta dizer que tudo isto é remediado em C ++ 11, onde se pode simplesmente usar nullptr vez de NULL, e também nullptr_t que é o tipo de um nullptr.

Eu diria que a história tem falado e aqueles que argumentou em favor do uso de 0 (zero) estavam errados (incluindo Bjarne Stroustrup). Os argumentos a favor de 0 eram principalmente estética e "preferência pessoal".

Após a criação do C ++ 11, com o seu novo tipo nullptr, alguns compiladores começaram a reclamar (com parâmetros padrão) sobre a passagem 0 a funções com argumentos de ponteiro, porque 0 não é um ponteiro.

Se o código foi escrito usando NULL, uma pesquisa simples e substituir poderia ter sido realizado através da base de código para torná-lo NullPtr vez. Se você está preso com o código escrito usando a escolha de 0 como um ponteiro é muito mais tediosa para atualizá-lo.

E se você tem que escrever um novo código agora para o C ++ 03 standard (e não pode usar nullptr), você realmente deve apenas usar NULL. Vai torná-lo muito mais fácil para você atualizar no futuro.

Eu costumo usar 0. eu não gosto de macros, e não há nenhuma garantia de que uma terceira cabeçalho festa que você está usando faz NULL não redefine a ser algo estranho.

Você pode usar um objeto nullptr como proposto por Scott Meyers e outros até C ++ recebe uma palavra-chave 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" para mais informações.

Uma vez eu trabalhava em uma máquina onde 0 é um endereço válido e NULL foi definida como um valor octal especial. Em que a máquina (0! = NULL), de modo que o código como

char *p;

...

if (p) { ... }

não iria funcionar como você espera. Você tinha que escrever

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

Embora eu acredito que a maioria compiladores definir NULL como 0 nestes dias eu ainda lembrar a lição a partir desses anos atrás: NULL não é necessariamente 0

.

Eu acho que as garantias padrão que NULL == 0, para que possa fazer qualquer um. Eu prefiro NULL porque documenta a sua intenção.

Usando 0 ou NULL terá o mesmo efeito.

No entanto, isso não significa que eles são ambos boas práticas de programação. Dado que não há diferença no desempenho, escolhendo uma opção de baixo nível consciente sobre uma alternativa agnóstico / abstract é uma prática de programação ruim. Ajuda leitores de seu código de compreender o seu processo de pensamento .

NULL, 0, 0,0, '\ 0', 0x00 e whatelse todos traduzir para a mesma coisa, mas são entidades lógicas diferentes em seu programa. Eles devem ser usados ??como tal. NULL é um ponteiro, 0 é a quantidade, 0x0 é um valor cujos bits são interessantes, etc Você não seria atribuir '\ 0' para um ponteiro se compila ou não.

Eu sei que algumas comunidades incentivar demonstrando conhecimento aprofundado de um ambiente quebrando contratos do ambiente. programadores responsáveis, no entanto, tornar o código sustentável e manter tais práticas fora de seu código.

Estranho, ninguém, incluindo Stroustroup mencionou isso. Ao falar muito sobre normas e estética ninguém notou que é perigoso usar 0 no lugar de NULL, por exemplo, na lista de argumentos variável na arquitetura, onde sizeof(int) != sizeof(void*). Como Stroustroup, eu prefiro 0 por razões estéticas, mas é preciso ter cuidado para não usá-lo onde seu tipo pode ser ambíguo.

Eu tento evitar toda a questão usando referências C ++ sempre que possível. Ao invés de

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

que você pode muitas vezes ser capaz de escrever

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

Claro, isso nem sempre funciona; mas ponteiros nulos pode ser usado em demasia.

Eu estou com Stroustrup em um presente :-) Desde NULL não é parte da linguagem, eu prefiro usar 0.

preferência Principalmente pessoal, embora se poderia fazer o argumento de que NULL torna bastante óbvio que o objeto é um ponteiro que atualmente não aponta para qualquer coisa, por exemplo.

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

IIRC, o padrão não requer NULL para ser 0, portanto, usando tudo o que é definida em é provavelmente melhor para o seu compilador.

Outra faceta ao argumento é se você deve usar comparações lógicas (conversão implícita para bool) ou cheque explicitamente contra NULL, mas que se resume a legibilidade também.

Eu prefiro usar NULL como ele deixa claro que sua intenção é o valor representa um ponteiro não um valor aritmética. O fato de que é uma macro é lamentável, mas uma vez que é tão amplamente enraizada há pouco perigo (a menos que alguém faz algo realmente boneheaded). Eu queria que fosse uma palavra-chave desde o início, mas o que você pode fazer?

Dito isso, eu não tenho nenhum problema com o uso de ponteiros como valores de verdade em si mesmos. Assim como com NULL, é uma linguagem enraizada.

C ++ 09 irá adicionar a construção do nullptr que eu acho que está muito atrasada.

Eu uso sempre 0. Não por qualquer pensamento real fora razão, só porque quando eu estava começando a aprender C ++ eu li algo que recomendou a utilização de 0 e acabo sempre fizemos dessa forma. Em teoria, não poderia ser um problema confusão na legibilidade mas na prática eu nunca uma vez se deparar com essa questão em milhares de horas de trabalho e milhões de linhas de código. Como diz Stroustrup, é realmente apenas uma questão de estética pessoal até que a norma se torne nullptr.

Alguém me disse uma vez ... Eu estou indo para NULL redefine a 69. Desde então, eu não usá-lo: P

Não faz o seu código muito vulnerável.

Editar:

Nem tudo no padrão é perfeito. O NULL macro é uma constante ponteiro nulo C ++ definido pela implementação não é totalmente compatível com C NULL macro, o que, além do tipo de esconder convertido implícita lo em uma ferramenta inútil e propenso a erros.

NULL não se comporta como um ponteiro nulo, mas como um O / OL literal.

Diga-me próximo exemplo não é confuso:

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

É por causa de tudo isso, nas novas aparece padrão std :: nullptr_t

Se você não quiser esperar para o novo padrão e quiser usar um nullptr, o uso de pelo menos um decente como o proposto por Meyers (ver comentário jon.h).

Bem, eu argumentar para não usar 0 ou nulo ponteiros em tudo sempre que possível.

Usando-los, mais cedo ou mais tarde levar a falhas de segmentação em seu código. Na minha experiência isto, e ponteiros em gereral é uma das maiores fontes de erros em C ++

Além disso, ele leva a "if-not-null" declarações em todo o seu código. Muito melhor se você pode confiar sempre um estado válido.

Há quase sempre uma alternativa melhor.

A definição de um ponteiro para 0 não é assim tão clara. Especialmente se você vir um idioma diferente do C ++. Isto inclui C, bem como Javascript.

Recentemente delt com algum código assim:

virtual void DrawTo(BITMAP *buffer) =0;

para a função virtual pura, pela primeira vez. Eu pensei que fosse algum jiberjash mágica por uma semana. Quando eu percebi que era apenas basicamente definir o ponteiro de função para um null (como funções virtuais são apenas ponteiros de função na maioria dos casos para C ++) me chutou.

virtual void DrawTo(BITMAP *buffer) =null;

teria sido menos confuso do que basterdation sem espaçamento adequado aos meus novos olhos. Na verdade, eu estou querendo saber porque C ++ não emprega null minúsculas bem como ele emprega falsa minúsculas e verdadeiro agora.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top