Alguém pode explicar por que os ponteiros não foram inicializados com NULL
?
Exemplo:
void test(){
char *buf;
if (!buf)
// whatever
}
O programa não entraria no if porque buf
não é nulo.
Gostaria de saber por que, em que caso precisamos de uma variável com lixo ativado, especialmente ponteiros para endereçar o lixo na memória?
c++
memory
pointers
initialization
Jonathan
fonte
fonte
Respostas:
Todos nós percebemos que o ponteiro (e outros tipos de POD) deve ser inicializado.
A questão então se torna 'quem deve inicializá-los'.
Bem, existem basicamente dois métodos:
Vamos supor que o compilador inicializou qualquer variável não inicializada explicitamente pelo desenvolvedor. Em seguida, nos deparamos com situações em que a inicialização da variável não era trivial e o motivo pelo qual o desenvolvedor não o fez no ponto de declaração foi que ele precisava executar alguma operação e depois atribuir.
Portanto, agora temos a situação em que o compilador adicionou uma instrução extra ao código que inicializa a variável como NULL e, posteriormente, o código do desenvolvedor é adicionado para fazer a inicialização correta. Ou, em outras condições, a variável potencialmente nunca é usada. Muitos desenvolvedores de C ++ gritariam mal em ambas as condições ao custo dessa instrução extra.
Não é apenas uma questão de tempo. Mas também espaço. Existem muitos ambientes em que ambos os recursos são escassos e os desenvolvedores também não querem desistir.
MAS : Você pode simular o efeito de forçar a inicialização. A maioria dos compiladores avisa sobre variáveis não inicializadas. Portanto, sempre coloco meu nível de alerta no nível mais alto possível. Em seguida, diga ao compilador para tratar todos os avisos como erros. Sob essas condições, a maioria dos compiladores irá gerar um erro para variáveis que não foram inicializadas, mas são usadas e, assim, evitarão que o código seja gerado.
fonte
Citando Bjarne Stroustrup em TC ++ PL (Edição Especial p.22):
fonte
D
faz Se você não quiser a inicialização, use esta sintaxefloat f = void;
ouint* ptr = void;
. Agora ele é inicializado por padrão, mas se você realmente precisar, pode parar o compilador de fazê-lo.Porque a inicialização leva tempo. E em C ++, a primeira coisa que você deve fazer com qualquer variável é inicializá-la explicitamente:
ou:
ou:
fonte
Porque um dos lemas do C ++ é:
Você não paga pelo que não usa
Por isso mesmo, o
operator[]
davector
classe não verifica se o índice está fora dos limites, por exemplo.fonte
Por razões históricas, principalmente porque é assim que é feito em C. Por que é feito assim em C, é outra questão, mas acho que o princípio do overhead zero estava envolvido de alguma forma nesta decisão de design.
fonte
Além disso, temos um aviso para quando você explodir: "é possivelmente usado antes de um valor atribuído" ou verbage semelhante dependendo do seu compilador.
Você compila com avisos, certo?
fonte
Existem poucas situações em que faz sentido que uma variável não seja inicializada, e a inicialização padrão tem um custo pequeno, então por que fazer isso?
C ++ não é C89. Inferno, mesmo C não é C89. Você pode misturar declarações e código, então você deve adiar a declaração até o momento em que você tenha um valor adequado para inicializar.
fonte
Um ponteiro é apenas outro tipo. Se você criar um
int
,char
ou qualquer outro POD tipo não é inicializado para zero, então por que um ponteiro? Isso pode ser considerado uma sobrecarga desnecessária para alguém que escreve um programa como este.Se você sabe que irá inicializá-lo, por que o programa deveria incorrer em um custo quando você cria pela primeira vez
pBuf
na parte superior do método? Este é o princípio de sobrecarga zero.fonte
Se quiser um ponteiro que sempre é inicializado como NULL, você pode usar um modelo C ++ para emular essa funcionalidade:
fonte
Foo *a
, você usaInitializedPointer<Foo> a
- Um exercício puramente acadêmico, poisFoo *a=0
é menos digitação. No entanto, o código acima é muito útil do ponto de vista educacional. Com uma pequena modificação (para o ctor / dtor e operações de atribuição de "espaço reservado"), ele poderia ser facilmente estendido para vários tipos de ponteiros inteligentes, incluindo ponteiros com escopo (que são liberados no destruidor) e ponteiros de contagem de referência adicionando inc / operações dec quando o m_pPointer é definido ou limpo.Observe que os dados estáticos são inicializados com 0 (a menos que você diga o contrário).
E sim, você deve sempre declarar suas variáveis o mais tarde possível e com um valor inicial. Código como
deve disparar sinos de alarme quando você lê-lo. Não sei se algum fiapo pode ser persuadido a reclamar disso, já que é 100% legal.
fonte
Outra possível razão, é que em ponteiros de tempo de link é dado um endereço, mas o endereçamento indireto / des-referenciação de um ponteiro é responsabilidade do programador. Normalmente, o compilador não dá a mínima, mas o fardo é passado para o programador para gerenciar os ponteiros e garantir que nenhum vazamento de memória ocorra.
Na verdade, em poucas palavras, eles são inicializados no sentido de que, no momento do link, a variável de ponteiro recebe um endereço. Em seu código de exemplo acima, isso com certeza travará ou gerará um SIGSEGV.
Por razões de sanidade, sempre inicialize os ponteiros para NULL, dessa forma, se houver qualquer tentativa de desreferenciá-lo sem
malloc
ounew
der uma dica ao programador sobre o motivo pelo qual o programa se comportou mal.Espero que isso ajude e faça sentido,
fonte
Bem, se C ++ inicializasse os ponteiros, o pessoal de C reclamando "C ++ é mais lento que C" teria algo real para se agarrar;)
fonte
C ++ vem de um background C - e existem algumas razões que voltam disso:
C, ainda mais que C ++, é uma substituição da linguagem assembly. Ele não faz nada que você não lhe diga para fazer. Portanto: Se você quiser ANULAR - faça!
Além disso, se você anula coisas em uma linguagem bare-metal como C, surgem automaticamente questões de consistência: Se você malhar alguma coisa - ela deve ser zerada automaticamente? Que tal uma estrutura criada na pilha? todos os bytes devem ser zerados? E quanto às variáveis globais? que tal uma declaração como "(* 0x18);" isso não significa que a posição 0x18 da memória deve ser zerada?
fonte
calloc()
.Quais são essas dicas de que você fala?
Para a segurança de exceção, use sempre
auto_ptr
,shared_ptr
,weak_ptr
e suas outras variantes.Uma marca registrada de um bom código é aquele que não inclui uma única chamada para
delete
.fonte
auto_ptr
e substituaunique_ptr
.Oh garoto. A verdadeira resposta é que é fácil zerar a memória, que é a inicialização básica para, digamos, um ponteiro. O que também não tem nada a ver com a inicialização do próprio objeto.
Considerando os avisos que a maioria dos compiladores dá nos níveis mais altos, não consigo imaginar programar no nível mais alto e tratá-los como erros. Desde que aumentá-los nunca me salvou, mesmo um bug em grandes quantidades de código produzido, não posso recomendar isso.
fonte
NULL
, inicializá-lo para isso também é um erro.