Aula 10 - Alcance e Tempo de Vida de Variáveis
Conceitos-Chave:
- variável global, variável que pode ser acedida em todos os blocos do programa
- variável local, variável que só pode ser acedida no bloco em que foi declarada
- operador resolução de alcance (::), operador para aceder a variáveis globais que tenham o mesmo identificador de uma variável local
- tempo de vida de uma variável, espaço de tempo em que uma determinada variável fica guardada na memória
- variáveis estáticas, variáveis que, embora locais (de um ponto de vista de alcance), possuem o mesmo tempo de vida de uma variável global
Declaração de variáveis globais e locais
Se já tentaram fazer algum programa, de certeza que já se depararam com diversos erros de compilação. Decerto que alguns foram por distração, mas outros poderão ter sido originados pelo simples facto de declarar uma variável localmente, em vez de declará-la globalmente. Se vos aconteceu, em parte foi culpa minha, por não ter explicado isto há mais tempo (embora tenha dado uma pequena introdução na aula 06), por isso esta aula é dedicada a explicar este conceito.
Primeiro de tudo, uma variável global é uma variável que poderá ser usada em todo o programa. Uma variável local só poderá ser usada no bloco ou função onde foi declarada.
Para podermos declarar uma variável global teremos que a declarar fora da definição de uma função ou um bloco. Para termos uma variável local teremos que declarar a variável dentro da definição de uma função ou um bloco. Está aqui um exemplo:
#include <iostream>
using namespace std;
int func();
int x = 100; //variável global, portanto pode ser usada em todo o programa
int main()
{
int y = 2; //variável local, só pode ser usada na função main()
return 0;
}
int func()
{
int z = 10; //variável local, só pode ser usada na função func()
return x;
}
Acho que já perceberam como se define uma variável global e uma variável local. Notem também que os argumentos de uma função são locais à mesma.
Variáveis globais e locais num programa
Para terem uma ideia prática dos vários erros que podemos cometer vejam este programa todo comentado:
#include <iostream>
using namespace std;
int i = 20; // variável global, usada no programa todo
void funcao();
int main()
{
int x; // declarar uma variável inteira
i = 30; // correcto, porque i é uma variável global!
funcao();
y = 20; //erro!!! y só foi declarado dentro da funcao() logo não está acessível dentro de main()
x = 10; //correcto, por x pertencer á funçao main
i = 20; //correcto
for (int a = 1; a < 10; a++)
{ //inicio do bloco
a = 2; //cuidado isto e um for infinito, já que a nunca passa de 2, não chegando, por isso a 10!!!!!
} //fim do bloco
a = 30; //errado!!! a só pode ser acedida dentro do for
cin.get();
return 0;
}
void funcao()
{
int y; //declarar uma variável dentro da funcao();
x = 30; //errado! x não está declarado nesta funçao();
y = 10; //correcto
i = 5; //correcto. i é uma variável global;
}
PS: Nem sequer tentem compilar este programa, pois está cheio de erros :D
Dica:
Alguns compiladores consideram a instrução for um caso à parte, ou seja, consideram que se uma variável for definida
dentro do bloco do for essa mesma variável irá pertencer à função onde está contida, em vez de pertencer somente ao
bloco:
for (int a = 0; a < 10; a++)
{ cout << a; }
a = 2 //em alguns compiladores isto daria erro, noutros estaria tudo bem....
Toda a teoria acima descrita está aplicada neste exemplo.
Operador resolução de alcance (::)
Vejam o seguinte exemplo:
#include <iostream>
using namespace std;
int x, y;
void andarDireita(int x);
int main()
{
x = 20;
andarDireita(15);
cout << x << endl;
cin.get();
return 0;
}
void andarDireita(int x)
{
::x += x; // a variável global x += a variável local x
}
Desta forma podemos usar variáveis globais, mesmo que existam variáveis locais com o mesmo nome dentro da função.
Memória e Tempo de Vida
Imaginem a memória como uma sequência
de bytes. Cada byte possui 2 tipos de valores: um número (o valor que
atribuímos) e um endereço.
Ao criarmos uma variável estaremos a colocar, num determinado endereço
da memória, um valor.
Imaginemos que estamos a olhar para a memória do computador (do endereço
93 a 107):
| 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
Agora se escrevêssemos em
C++:
int x = 70;
| 70 | ||||||||||||||
| 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
PS: A tabela não representa totalmente a realidade, pois cada int ocupa 4 bytes (deveria estar escrito em binário e não em decimal), mas acho que perceberam a ideia....
Isto serviu para vocês tentarem visualizar o que é a memória do computador.
Como devem saber a memória que temos disponível no computador é limitada e, por isso, em programas maiores, teremos que ter cuidado para poupar o máximo possível de memória. O próprio C++ faz isso, de uma maneira simples. As variáveis globais irão estar sempre alocadas na memória (até o programa desligar) enquanto as variáveis locais só irão ser alocadas na memória quando a função ou o bloco for chamado e irão ser eliminadas quando a função ou bloco termina.
Variáveis estáticas (static)
Vejam este exemplo:
#include <iostream>
using namespace std;
int incrementar(); //função que tem como objectivo incrementar um valor
int h; //variável global
int main()
{
for (int x = 0; x < 10; x++)
{
h = incrementar(); //incrementar 10 vezes a variável h global
}
cout << h << endl; //mostrar o resultado
cin.get();
return 0;
}
int incrementar()
{
int h = 0; //cria uma variável local
//notem que não existe conflito com a variável global
//que tem o mesmo nome.
h++; //incrementa
return h; //devolve o resultado
}
O objectivo do programa era obter, no final, o valor de 10. No entanto obtemos o valor de 1. Porquê?
A resposta está no tempo de vida da variável local h. Ela é construída e destruída 10 vezes. Cada vez que é destruída perde qualquer valor guardado e cada vez que é construída ela assume o valor de 0. Para remediar isto o melhor é construir uma variável estática, através da keyword static.
#include <iostream>
using namespace std;
int incrementar(); //função que tem como objectivo incrementar um valor
int h; //variável global
int main()
{
for (int x = 0; x < 10; x++)
{
h = incrementar(); //incrementar 10 vezes a variável h global
}
cout << h << endl; //mostrar o resultado
cin.get();
return 0;
}
int incrementar()
{
static int h = 0; //cria uma variável local estática
//notem que não existe conflito com a variável global
//que tem o mesmo nome.
h++; //incrementa
return h; //devolve o resultado
}
Uma variável estática tem o mesmo tempo de vida de uma variável global (é iniciada no início do programa e destruída no fim), mas possui o alcance de uma variável local (não pode ser usada fora da função onde foi declarada).
Aviso:
Temos que atribuir sempre um valor quando declaramos uma variável estática
Dica:
Se declararmos uma variável global sem atribuirmos um valor, esta vai adquirir o valor 0.
Se declararmos uma variável local sem atribuirmos um valor, esta vai adquirir um valor aleatório.
Próxima aula -> C++ 11 - Referências e Apontadores
Fazer o download do código fonte dos exemplos da aula
Fazer o download da aula em PDF (Brevemente)
Ir para o topo da página