Aula 24: Ponteiros e Alocação Dinâmica
Introdução a Programação
Túlio Toffolo & Puca Huachi http://www.toffolo.com.br
Aula anterior
Memória Ponteiro
Utilização de ponteiros Aritmética de ponteiros
Aula de hoje
1 Ponteiros
2 Exercícios da aula prática 3 Mais exemplos...
4 Alocação dinâmica 5 Exercícios
Aula de hoje
1 Ponteiros
2 Exercícios da aula prática
3 Mais exemplos...
4 Alocação dinâmica
5 Exercícios
Ponteiros
Um ponteiro (apontador ou pointer) é um tipo especial de variável que armazena umendereço de memória
Ponteiros são declarados utilizando o caractere especial
*
:1 int *pi; // pi é um ponteiro do tipo int
2 char *pc; // pc é um ponteiro do tipo char
3 float *pf; // pf é um ponteiro do tipo float
4 double *pd; // pd é um ponteiro do tipo double
Vários podem ser declarados em uma única linha:
Ponteiros
Oconteúdoda memória apontada por um ponteiro se refere ao valor armazenado no endereço de memória para o qual o ponteiro aponta.
Este conteúdo (valor) pode ser alterado usando o operador
*
Exemplo:
1 int main()
2 {
3 int x = 10, y = 0;
4 int *px = &x;
5 → y = *px; // y recebe o conteúdo do endereço apontado por x
6 cout << "y = " << y << endl;
7 return 0;
8 }
O que será impresso?
Ponteiros
Cuidado com o uso do
*
:Não confundadeclaração de ponteirocom obtenção deconteúdo... O
*
a seguir é utilizado paradeclarar um ponteiro1 int *p;
Já o
*
a seguir é utilizado para obter/alterar oconteúdoda memória armazenada por um ponteiro.1 *p = 10;
2 if ((*p) > 10)
Aula de hoje
1 Ponteiros
2 Exercícios da aula prática
3 Mais exemplos...
4 Alocação dinâmica
5 Exercícios
Exercício 1
Faça um programa em C++ que encontre a última ocorrência de um caractere dentro de uma cadeia de caracteres (máximo 256 caracteres). Para isso implemente uma função que recebe a cadeia de caracteres e retorna um ponteiro para a posição. O main() deve imprimir o valor dessa posição considerando que a primeira posição é a 1.
Protótipo:
1 char* procuraUltimo(char *, char);
Exemplo:
1 Digite um texto: Teste de execução
2 Digite o caractere para procurar: e
3
Exercícios da aula prática
Exercício 2
Faça um programa que leia
n
valores, onden ≤ 100
, pertencentes ao conjunto dos números reais. Em seguida, implemente a funçãomaior()
que recebe esse vetor e retorna um ponteiro para a posição no vetor do maior elemento. Imprima a posição (endereço de memória) e o valor do maior elemento no módulo principal.
Exercício 3
Faça um programa que leia
n
valores (n ≤ 9
), em ordem crescente, pertencentes ao conjunto dos números inteiros. Em seguida, leia um número inteiro qualquer e insira nesse vetor, mantendo a ordem. Imprima o novo vetor.Aula de hoje
1 Ponteiros
2 Exercícios da aula prática
3 Mais exemplos...
4 Alocação dinâmica
5 Exercícios
Mais exemplos...
Passagem de apontadores IV
1 void troca(int *a, int *b) {
2 int aux = *a; 3 *a = *b; 4 *b = aux; 5 } 6 7 int main() { 8 int n = 5; 9 int v[5] = { 10, 20, 30, 40, 0 }; 10
11 cin >> v[n-1]; // lendo mais um nro
12 for (int i = n-1; i >= 1; i++) { 13 if (v[i] < v[i-1]) 14 troca(v+i, v+i-1); 15 else 16 break; 17 } 18 19 imprimeVetor(v, n); 20 }
Mais exemplos...
Passagem de apontadores IV
1 int *ultimo(int *v, int b, int n) {
2 int *p = v; 3 for (int i = 1; i < n; i++) { 4 if (v[i] == b) 5 p = v+i; 6 } 7 return p; 8 } 9 10 int main() { 11 int v[7] = { 0, 9, 8, 6, 5, 3, 2 }; 12 int busca; 13 cin >> busca; 14
15 int *p = ultimo(v, busca, 7);
16
17 int pos = p - v;
18 cout << "Pos = " << pos + 1 << endl;
19
20 return 0;
Aula de hoje
1 Ponteiros
2 Exercícios da aula prática
3 Mais exemplos...
4 Alocação dinâmica
5 Exercícios
Alocação dinâmica
Comando
new
:Aloca dinamicamente um bloco consecutivo de bytes na memória e retorna o endereço deste bloco.
Isto permite escrever programas mais flexíveis.
Alocação dinâmica
Uso do método
new
para criar umdouble
:1 // aloca memória de forma dinâmica
2 double *nro = new double;
3
4 // altera o conteúdo da memória apontada por nro para 3.5
5 *nro = 3.5;
6
7 cout << "Endereço de memória: " << nro << endl;
8 cout << "Valor na memória: " << *nro << endl;
Este código imprimirá, por exemplo (arquitetura 64 bits):
1 Endereço de memória: 0x7feaf4400690
Alocação dinâmica
Uso do método
new
para criar umdouble
com valor inicial:1 // aloca memória de forma dinâmica e inicializa com valor 10.5
2 double *nro = new double(10.5);
3
4 cout << "Endereço de memória: " << nro << endl;
5 cout << "Valor na memória: " << *nro << endl;
Este código imprimirá, por exemplo (arquitetura 64 bits):
1 Endereço de memória: 0x7feaf4400690
Alocação dinâmica
Uso do método
new
para criar um bloco com 3 doubles:1 // aloca memória de forma dinâmica e inicializa com valor 10.5
2 double *nro = new double[3];
3 4 // alterando valores 5 nro[0] = 1.1; 6 nro[1] = 1.5; 7 nro[2] = 2.2; 8 9 for (int i = 0; i < 3; i++) 10 cout << nro[i] << " ";
Este código imprimirá:
Exemplo de alocação dinâmica
Aloca¸c˜ao dinˆamica de mem´oria VIII
1 int main() { 2 → int *a = nullptr; 3 a = new int[6]; 4 for (int i = 0; i < 6; i++) 5 a[i] = i; 6 imprimeVetor3(a, 6); 7 ... 8 }
Cria o ponteiro
a
com valor inicialExemplo de alocação dinâmica
Aloca¸c˜ao dinˆamica de mem´oria IX
1 int main() { 2 int *a = nullptr; 3 → a = new int[6]; 4 for (int i = 0; i < 6; i++) 5 a[i] = i; 6 imprimeVetor3(a, 6); 7 ... 8 }
Aloca um bloco de memória com 6 inteiros (usando o comando
new
)Armazena o endereço de memória no ponteiro
a
.Exemplo de alocação dinâmica
Aloca¸c˜ao dinˆamica de mem´oria X
1 int main() { 2 int *a = nullptr; 3 a = new int[6]; 4 → for (int i = 0; i < 6; i++) 5 → a[i] = i; 6 imprimeVetor3(a, 6); 7 ... 8 }
Altera o valor de
a[0]
,a[1]
, ...,Muito importante: liberar a memória
A memória alocada pelo compilado é liberada ao final do escopo da variável automaticamente.
Quando fazemos alocação dinâmica, é nossa obrigaçãoliberar a memória.
Em C++ usamos o operador
delete
Exemplo (1):
1 int *a = new int;
2 ...
Muito importante: liberar a memória
A memória alocada pelo compilado é liberada ao final do escopo da variável automaticamente.
Quando fazemos alocação dinâmica, é nossa obrigaçãoliberar a memória.
Em C++ usamos o operador
delete
Exemplo (2):
1 int *v = new int[6];
2 ...
Exemplos
Passagem de apontadores IV
1 void leVetor(int *v, int n) {
2 for (int i = 0; i < n; i++)
3 cin >> v[i];
4 }
5
6 int *maior(int *v, int n) {
7 int *maior = v; 8 for (int i = 1; i < n; i++) 9 if (v[i] > *maior) 10 maior = v + i; 11 return maior; 12 } 13 14 int main() { 15 int n, *v; 16 cin >> n; 17 v = new int[n]; 18 leVetor(v, n);
19 int *maior = maior(v, n);
20 cout << "Maior = " << *maior << endl;
21 delete[] v;
Aula de hoje
1 Ponteiros
2 Exercícios da aula prática
3 Mais exemplos...
4 Alocação dinâmica
5 Exercícios
Exercícios
Exercício 1Crie uma função que:
1 recebe um vetor
v
e seu tamanhon
por parâmetro;2 cria um novo vetor por alocação dinâmica, preenchendo-o com o
conteúdo de
v
em ordem inversa;3 retorna este novo vetor.
Dica: utilize o protótipo a seguir:
1 int *inverso(int *v, int n);
Crie um exemplo de utilização desta função no método
main()
. Não se esqueça de liberar memória!Aula de hoje
1 Ponteiros
2 Exercícios da aula prática
3 Mais exemplos...
4 Alocação dinâmica
5 Exercícios