O que é uma variável
Uma variável é um trecho de memória com nome que contém um valor. Em C++, toda variável tem um tipo fixo - escolhido quando você a declara - e esse tipo nunca muda. É isso que torna C++ uma linguagem de tipagem estática: o compilador conhece o tipo de cada variável antes de o programa rodar e se recusa a compilar código que armazene um valor do tipo errado.
Uma declaração tem três partes: o tipo, o nome e (quase sempre) um valor inicial.
Leia int age = 30; como "crie um int chamado age e coloque 30 nele". O ponto e vírgula encerra a instrução, exatamente como a página de comentários mostrou que toda instrução faz. Note que isActive foi impresso como 1: um bool aparece como 1/0 por padrão, algo sobre o qual a página de tipos de dados se baseia.
Inicialização vs. atribuição
As duas parecem semelhantes, mas são operações diferentes, e essa diferença é uma das ideias mais importantes desta página.
A inicialização dá à variável seu primeiro valor como parte da declaração. A atribuição muda o valor de uma variável que já existe.
Você pode declarar sem inicializar e atribuir depois, mas tome cuidado:
Isso funciona porque atribuímos score antes de lê-lo. A versão perigosa é lê-lo primeiro, o que veremos a seguir.
A armadilha da variável não inicializada
Esta é a armadilha clássica de C++ que não existe em muitas outras linguagens. Ler uma variável local que foi declarada mas nunca recebeu um valor é comportamento indefinido: a variável contém os bytes que por acaso estavam naquela memória.
int score; // não inicializada
std::cout << score; // comportamento indefinido - imprime lixo, ou "funciona", ou trava
O compilador construirá isso sem reclamar. Pode imprimir 0, pode imprimir 32766, e pode se comportar de forma diferente a cada execução ou em cada máquina - o que torna esses bugs terríveis de rastrear. Duas defesas:
- Sempre inicialize na declaração.
int score = 0;não custa nada e elimina o problema por completo. - Ative os avisos. Compilar com
-Wall -Wextrafaz o compilador apontar muitas leituras não inicializadas antes que elas te mordam.
Prefira a primeira opção para toda variável local: dê a ela um valor inicial sensato no exato momento em que a cria.
Estilos de inicialização: =, () e {}
C++ oferece algumas maneiras de escrever um valor inicial. Na maioria das vezes elas fazem a mesma coisa, mas a inicialização com chaves tem um recurso extra de segurança que vale a pena conhecer.
O motivo para recorrer a {} é que ela rejeita conversões com estreitamento (narrowing): atribuições que perderiam dados silenciosamente. Com =, um valor fracionário é truncado sem aviso; com {}, o compilador te impede:
int x = 3.9; // compila - x se torna silenciosamente 3 (o .9 é descartado)
int y{3.9}; // erro de compilação - o estreitamento de double para int não é permitido
Pegar isso em tempo de compilação é exatamente o que você quer. Um hábito moderno comum é usar {} por padrão para essa verificação extra, recorrendo a = apenas quando a inicialização por cópia se lê de forma mais natural.
Regras e convenções de nomes
C++ impõe algumas regras rígidas e, em cima delas, todos acrescentam convenções. As regras: um nome pode conter letras, dígitos e _; não pode começar com um dígito; não pode ser uma palavra reservada (como int ou return); e diferencia maiúsculas de minúsculas (age e Age são duas variáveis diferentes). Evite nomes que comecem com um sublinhado seguido de uma letra maiúscula, ou que contenham dois sublinhados seguidos: esses são reservados para a implementação.
As convenções que a maioria do código C++ segue:
- Variáveis usam
snake_caseoucamelCase- escolha uma e mantenha a consistência:item_countouitemCount. - Os nomes devem descrever o valor:
count, nãoc;user_email, nãox.
Nomes claros não são enfeite: são a forma como o seu eu do futuro lê o código. total_price = item_count * price_per_item se explica sozinho de um jeito que t = c * p nunca conseguirá.
Escopo de variáveis
Uma variável existe apenas dentro do bloco - as { ... } - onde é declarada, e é destruída na chave de fechamento. Isso é o seu escopo (scope). Uma variável declarada dentro de um laço ou de um bloco if é invisível fora dele:
Tanto i quanto square pertencem ao laço e desaparecem quando ele termina; total é declarado no bloco externo, então sobrevive. Um bloco interno também pode ofuscar (shadow) um nome de um bloco externo: uma nova variável com o mesmo nome esconde temporariamente a externa até que o bloco interno se feche, o que é uma fonte frequente de confusão, então evite reutilizar nomes entre escopos aninhados.
A lição prática: declare cada variável no menor bloco que precisar dela e inicialize-a ali. Um escopo restrito significa menos nomes competindo pela sua atenção e menos chances de ler um valor longe de onde ele foi definido.
Próximo: Tipos de dados
Toda variável desta página começou com um tipo - int, double, string, bool. A próxima página detalha os tipos de dados de C++: os tipos fundamentais e seus tamanhos, inteiros com e sem sinal, float vs. double, char, e como escolher o tipo certo para cada tarefa.
Perguntas frequentes
Como se declara uma variável em C++?
Escreva o tipo, depois um nome e, opcionalmente, dê um valor a ela: int age = 30;. O tipo (int) é fixo por toda a vida da variável; o nome (age) é como você se refere a ela. Você pode declará-la sem valor - int age; -, mas, no caso de uma variável local, isso a deixa com lixo até que você atribua um valor, então sempre inicialize no ponto da declaração.
Qual é a diferença entre inicialização e atribuição em C++?
A inicialização dá à variável seu primeiro valor como parte da declaração: int x = 5; ou int x{5};. A atribuição muda o valor de uma variável que já existe: x = 7;. A distinção importa porque ler uma variável local que foi declarada mas nunca inicializada é comportamento indefinido.
O que acontece se você usar uma variável não inicializada em C++?
Ler o valor de uma variável local não inicializada é comportamento indefinido: a variável contém os bytes que já estavam naquela memória, então seu programa pode imprimir um número aleatório, funcionar por sorte ou travar. O compilador não vai impedir você (embora muitos avisem com -Wall), então a solução é sempre dar um valor às variáveis locais ao declará-las.