Muitas vezes vejo nos códigos C e C ++ a seguinte convenção:
some_type val;
val = something;
some_type *ptr = NULL;
ptr = &something_else;
ao invés de
some_type val = something;
some_type *ptr = &something_else;
Inicialmente, assumi que esse era um hábito que restava desde os dias em que você tinha que declarar todas as variáveis locais no topo do escopo. Mas aprendi a não descartar tão rapidamente os hábitos dos desenvolvedores veteranos. Então, há uma boa razão para declarar em uma linha e atribuir depois?
Respostas:
C
No C89, todas as declarações tinham que estar no início de um escopo (
{ ... }
), mas esse requisito foi eliminado rapidamente (primeiro com extensões do compilador e depois com o padrão).C ++
Esses exemplos não são os mesmos.
some_type val = something;
chama o construtor de cópia, enquantoval = something;
chama o construtor padrão e, em seguida, aoperator=
função Essa diferença é frequentemente crítica.Hábitos
Algumas pessoas preferem primeiro declarar variáveis e depois defini-las, caso estejam reformatando seu código posteriormente com as declarações em um ponto e a definição em outro.
Sobre os ponteiros, algumas pessoas têm o hábito de inicializar todos os ponteiros
NULL
ounullptr
, não importa o que façam com esse ponteiro.fonte
some_type
construtor tomandosomething
como único argumento. Este é um caso de borda muito interessante e incomum em C ++ ... significa que há uma presunção sobre o significado semântico dessas operações.Você marcou sua pergunta C e C ++ ao mesmo tempo, enquanto a resposta é significativamente diferente nesses idiomas.
Em primeiro lugar, a redação do título da sua pergunta está incorreta (ou, mais precisamente, irrelevante para a própria pergunta). Nos dois exemplos, a variável é declarada e definida simultaneamente, em uma linha. A diferença entre seus exemplos é que, no primeiro, as variáveis são deixadas não inicializadas ou inicializadas com um valor fictício e, em seguida, é atribuído um valor significativo posteriormente. No segundo exemplo, as variáveis são inicializadas imediatamente.
Em segundo lugar, na linguagem C ++, como o @nightcracker observou em sua resposta, essas duas construções são semanticamente diferentes. O primeiro depende da inicialização, enquanto o segundo - da atribuição. Em C ++, essas operações são sobrecarregáveis e, portanto, podem potencialmente levar a resultados diferentes (embora se possa observar que produzir sobrecargas não equivalentes de inicialização e atribuição não é uma boa idéia).
Na linguagem C padrão original (C89 / 90), é ilegal declarar variáveis no meio do bloco, e é por isso que você pode ver variáveis declaradas não inicializadas (ou inicializadas com valores fictícios) no início do bloco e depois atribuídas significativas valores posteriormente, quando esses valores significativos estiverem disponíveis.
Na linguagem C99, não há problema em declarar variáveis no meio do bloco (assim como em C ++), o que significa que a primeira abordagem é necessária apenas em algumas situações específicas quando o inicializador não é conhecido no ponto de declaração. (Isso também se aplica ao C ++).
fonte
some_type val;
imediatamente declara e define a variávelval
. Foi isso que eu quis dizer na minha resposta.Eu acho que é um hábito antigo, sobra dos tempos da "declaração local". E, portanto, como resposta à sua pergunta: Não, acho que não há uma boa razão. Eu nunca faço isso sozinho.
fonte
Eu disse algo sobre isso na minha resposta a uma pergunta do Helium3 .
Basicamente, eu digo que é uma ajuda visual ver facilmente o que mudou.
e
fonte
As outras respostas são muito boas. Há alguma história em torno disso em C. No C ++, há a diferença entre um construtor e um operador de atribuição.
Estou surpreso que ninguém mencione o ponto adicional: manter as declarações separadas do uso de uma variável às vezes pode ser muito mais legível.
Visualmente falando, ao ler código, os artefatos mais mundanos, como os tipos e nomes de variáveis, não são o que chamam a atenção. É nas frases em que você mais se interessa, passa mais tempo olhando e, portanto, há uma tendência a olhar para o resto.
Se eu tenho alguns tipos, nomes e tarefas todos no mesmo espaço, é uma sobrecarga de informações. Além disso, significa que algo importante está acontecendo no espaço que eu geralmente olho.
Pode parecer um pouco contra-intuitivo dizer, mas esse é um exemplo em que fazer com que sua fonte ocupe mais espaço vertical pode torná-lo melhor. Eu vejo isso como um motivo pelo qual você não deve escrever linhas cheias de atolamentos que fazem quantidades loucas de aritmética e atribuição de ponteiros em um espaço vertical apertado - só porque o idioma permite que você se dê bem com essas coisas não significa que você deve fazer isso o tempo todo. :-)
fonte
Em C, essa era a prática padrão porque as variáveis tinham que ser declaradas no início da função, diferentemente do C ++, onde podiam ser declaradas em qualquer lugar do corpo da função para serem usadas posteriormente. Os ponteiros foram definidos como 0 ou NULL, porque apenas garantiram que o ponteiro não apontasse lixo. Caso contrário, não há vantagem significativa em que eu possa pensar, o que leva qualquer pessoa a fazer assim.
fonte
Prós por localizar definições de variáveis e sua inicialização significativa:
se as variáveis recebem habitualmente um valor significativo quando aparecem pela primeira vez no código (outra perspectiva da mesma coisa: você atrasa a aparência até que um valor significativo esteja disponível), então não há chance delas serem acidentalmente usadas com um valor sem significado ou não inicializado ( o que pode acontecer facilmente é que alguma inicialização é ignorada acidentalmente devido a declarações condicionais, avaliação de curto-circuito, exceções etc.)
pode ser mais eficiente
operator=
Às vezes, pode ser menos eficiente e exigir um objeto temporáriominimizar o escopo de variáveis, por sua vez, minimiza o número médio de variáveis simultaneamente no escopo : isso
às vezes, mais conciso, pois você não está repetindo o nome da variável em uma definição e em uma atribuição significativa inicial
necessário para certos tipos, como referências e quando você deseja que o objeto seja
const
Argumentos para agrupar definições de variáveis:
às vezes é conveniente e / ou conciso fatorar o tipo de um número de variáveis:
the_same_type v1, v2, v3;
(se o motivo for o fato de o nome do tipo ser muito longo ou complexo,
typedef
às vezes pode ser melhor)às vezes é desejável agrupar variáveis independentemente de seu uso para enfatizar o conjunto de variáveis (e tipos) envolvidos em alguma operação:
type v1;
type v2;
type v3;
Isso enfatiza a semelhança de tipo e facilita um pouco sua alteração, mantendo uma variável por linha que facilita copiar e colar,
//
comentar etc.Como geralmente acontece na programação, embora possa haver um benefício empírico claro para uma prática na maioria das situações, a outra prática pode realmente ser extremamente melhor em alguns casos.
fonte