Pearson Education Slide 1. Pearson Education Slide 2 Cap í tulo 10 Criado por Frederick H....
Transcript of Pearson Education Slide 1. Pearson Education Slide 2 Cap í tulo 10 Criado por Frederick H....
Pearson Education Slide 1
Pearson Education Slide 2
Capítulo 10
Criado por Frederick H. Colclough, Colorado Technical University
Ponteiros e Vetores Dinâmicos
Pearson Education Slide 3
Objetivos do Estudo Ponteiros
Variáveis ponteiro Gerenciamento de memória
Vetores Dinâmicos Criando e usando Aritmética de ponteiros
Classes, Ponteiros e Vetores dinâmicos O ponteiro this Destrutores e Construtores de cópia
Pearson Education Slide 4
Introdução aos Ponteiros Definição de ponteiro :
Endereço de memória para uma variável Lembre-se: A memória é dividida
Em posições numeradas Endereços usados como nomes para
variáveis Você já usou ponteiros!
Argumentos chamados-por-referência O endereço do argumento atual foi passado
Pearson Education Slide 5
Variáveis Ponteiro Ponteiros são ‘digitados’
Pode-se armazenar um ponteiro em uma variável Não int, double, etc.
Em vez disso: UM PONTEIRO para int, double, etc!
Exemplo:double *p;
p é declarado como um ‘ponteiro para a variável double
Pode-se armazenar ponteiros para variável de tipo double
Não para outros tipos!
Pearson Education Slide 6
Declarando Variáveis Ponteiro Ponteiros são declarados assim como outros
tipos Adicionar ‘*’ antes do nome da variável Gera um ‘ponteiro para’ aquele tipo
‘*’ deve estar antes de cada variável int *p1, *p2, v1, v2;
p1, p2 armazenam ponteiros para variáveis int
v1, v2 são variáveis comuns de tipo int
Pearson Education Slide 7
Endereços e Números Ponteiro é um endereço Endereço é um inteiro Ponteiro não é um inteiro!
Não é loucura é abstração! O C++ insiste em que você utilize um
ponteiro como um endereço Mesmo que ele ‘seja um’ número
Pearson Education Slide 8
Apontar Terminologia e visão
Fale em ‘apontar’, não em ‘endereços’ Variável ponteiro ‘aponta para’ a variável
comum
Torna a visualização mais clara
Pearson Education Slide 9
Apontar para … int *p1, *p2, v1, v2;
p1 = &v1; Faz a variável ponteiro p1 ‘apontar para’ a
variável int v1 Operador, &
Determina o ‘endereço da’ variável Lê-se:
“p1 é igual ao enderaço de v1” ou “p1 aponta para v1”
Pearson Education Slide 10
Apontar para … Lembre-se:
int *p1, *p2, v1, v2;p1 = &v1;
Agora temos dois modos de nos referirmos a v1: A variável v1 propriamente dita:
cout << v1; Através do ponteiro p1:
cout *p1; Operador de desreferenciação, * Variável ponteiro ‘desreferenciada’
Significa: “Obter dados para os quais p1 aponta”
Pearson Education Slide 11
Exemplo de ‘Apontar para’ Considere:
v1 = 0;p1 = &v1;*p1 = 42;cout << v1 << endl;cout << *p1 << endl;
Gera a seguinte saída:4242
p1 e v1 referem-se a mesma variável
Pearson Education Slide 12
Operador & O operador ‘de endereço’ Também usado para especificar
parâmetro
chamado-por-referência Não é coincidência! Lembre-se: parâmetros chamados-por-referência
passam o ‘endereço do’ argumento atual Os dois usos do operador estão intimamente
relacionados
Pearson Education Slide 13
Ponteiro: Atribuições Pode-se atribuir o valor de uma variável
ponteiro:int *p1, *p2;p2 = p1;
Atribui um ponteiro a outro “Faz p2 apontar para onde p1 aponta”
Não vá confundir com:*p1 = *p2;
Não se está lidando com os ponteiros p1 e p2, e sim
com as variáveis para as quais os ponteiros estão
apontando
Pearson Education Slide 14
Gráfico de Atribuição de PonteirosPainel 10.1 página 280
Pearson Education Slide 15
O Operador new Como um ponteiro pode se referir a uma
variável… Não é preciso ter um identificador padrão
Podemos alocar variáveis dinamicamente O operator new cria variáveis
Nenhum identificador para referir-se à elas Somente um ponteiro!
p1 = new int; Cria uma variável nova ‘sem nome’ e atribui
à p1 que passa a ‘apontar para’ ela Pode-se acessar com *p1
O uso é exatamente igual às variáveis simples
Pearson Education Slide 16
Exemplo de Manipulações Básicas de Ponteiro
Painel 10.2 página 281
Pearson Education Slide 17
Exemplo de Manipulações Básicas de Ponteiro (cont)
Painel 10.2 página 282
Pearson Education Slide 18
Manipulações Básicas de Ponteiro: Gráfico
Painel 10.3
página 282
Pearson Education Slide 19
Mais sobre o Operador new Cria uma variável dinâmica nova Retorna um ponteiro que aponta para a variável Se o tipo for tipo-classe:
Construtor-padrão é chamado para o novo objeto Pode-se especificar um construtor diferente
incluíndo argumento da seguinte forma:MeuTipo *mtPtr;mtPtr = new MeuTipo(32.0, 17);
Pode-se ainda inicializar tipos não-classe:int *n;n = new int(17); // inicializa *n como 17
Pearson Education Slide 20
Ponteiros e Funções Ponteiros são tipos completos
Podem ser usados exatamente como outros tipos
Podem ser parâmetros de funções Podem ser retornados por funções Exemplo:
int* encontreOutroPonteiro(int* p); Esta declaração de função:
Tem um ‘ponteiro para um’ parâmetro int Retorna ‘ponteiro para uma’ variável int
Pearson Education Slide 21
Gerenciamento de Memória Pilha
Também chamada de ‘freestore’ Reservada para variáveis dinamicamente
alocadas Qualquer variável dinâmica criada consome
memória na pilha Se muitas podem consumir toda a
memória
da pilha Se isso acontecer, qualquer chamada
adicional a new falhará.
Pearson Education Slide 22
Verificando o Sucesso new Compiladores antigos:
Testam se NULL foi retornado pela chamada a new:int *p;
p = new int;
if (p == NULL)
{
cout << "Erro: Memória insuficiente.\n";
exit(1);
}
//Se new foi bem-sucedido, o programa continua
a partir daqui.
Pearson Education Slide 23
new Bem-sucedida – Compilador Novo
Compiladores mais novos: Se a chamada new falhar:
O programa termina automaticamente Produzindo uma mensagem de erro
Ainda é uma boa prática usar a verificação
de NULL
Pearson Education Slide 24
Tamanho da Pilha Varia de uma implementação para outra Geralmente é grande
A maioria dos programas não utilizarão toda
a memória Gerenciamento de Memória
Ainda é uma boa prática Princípio sólido de Engenharia de Software A memória é finita
independente de quanto se tenha!
Pearson Education Slide 25
Operador delete Desaloca memória dinâmica
Quando não é mais necessária Devolve a memória para a pilha Exemplo:
int *p;p = new int(5);… //processando…delete p;
Desaloca memória dinâmica “apontada peloponteiro p”
Literalmente ‘destrói’ a variável dinâmica
Pearson Education Slide 26
Ponteiros Oscilantes delete p;
Destrói a variável dinâmica mas p ainda aponta para lá!
Chamado ‘Ponteiro Oscilante’ Se p for então desreferenciado ( *p )
Resultados serão imprevisíveis! Freqüentemente desastrosos!
Evite os ponteiros oscilantes Fixe-os como NULL antes de desreferenciá-
los:delete p;p = NULL;
Pearson Education Slide 27
Variáveis Dinâmicas e Automáticas Variáveis Dinâmicas
Criadas com o operador new Criadas e destruídas durante a execução do programa
Variáveis locais Declaradas dentro de uma definição de função Não-dinâmicas
Criadas quando a função é chamada Destruídas quando a chamada de função é completada. Geralmente são chamadas de variáveis
‘automáticas’ Propriedades controladas por você
Pearson Education Slide 28
Definindo Tipos Ponteiro Pode-se definir um nome de tipo ponteiro
de modo que as variáveis ponteiros possam
ser declaradas como outras variáveis Elimina a necessidade de colocar ‘*’ na declaração do ponteiro
typedef int* IntPtr; Define um ‘novo tipo’ (alias) Considere estas declarações:
IntPtr p;int *p;
As duas são eqüivalentes
Pearson Education Slide 29
Armadilha:Ponteiros como Parâmetros Chamados por Valor
Comportamento imprevisível e problemático
Se a função modifica o parâmetro ponteiro modifica apenas na cópia local
Melhor ilustrado no exemplo…
Pearson Education Slide 30
Exemplo:Ponteiros como Parâmetros Chamados por Valor
Painel 10.4 página 287
Pearson Education Slide 31
Exemplo: Ponteiros como Parâmetros Chamados por Valor (cont)
Painel 10.4 página 288
Pearson Education Slide 32
Gráfico de Ponteiros como Parâmetros Chamados por Valor
Painel 10.5 página 288
Pearson Education Slide 33
Vetores Dinâmicos Variáveis vetores
Na verdade são variáveis ponteiros.! Vetor-padrão
Tamanho fixo Vetor dinâmico
Tamanho não especificado quando se escreve
o programa Determinado enquanto o programa é
executado
Pearson Education Slide 34
Variáveis vetores Lembre-se: vetores são armazenados em
endereços de memória, seqüencialmente A variável vetor ‘refere-se’ à 1a variável indexada Então a variável vetor é um tipo de variável
ponteiro!
Exemplo:int a[10];int * p;
a e p são ambas variáveis ponteiro!
Pearson Education Slide 35
Variáveis Vetor Ponteiros Lembre-se do exemplo anterior:
int a[10];typedef int* IntPtr;IntPtr p;
a e p são variáveis ponteiro Podem atribuir:
p = a; // Legal. p agora aponta para onde a aponta
Para 1a variável indexada do vetor a a = p; // ILEGAL!
Pearson Education Slide 36
Variáveis Vetor Ponteiros Variável vetor
int a[10]; MAIS do que uma variável ponteiro
‘const int *’ type O vetor já estava alocado na memória A variável a DEVE apontar pará lá…
sempre! Não pode ser modificada!
Em comparação com ponteiros simples Os quais podem (e tipicamente) o fazem
Pearson Education Slide 37
Vetores Dinâmicos Limitações dos Vetores
Precisa-se especificar o tamanho Pode não ser conhecido até o programa ser
executado! DEVE-SE ‘estimar’ o tamanho máximo
necessário Agumas vezes OK, outras não ‘Gasto’ de memória
Vetores Dinâmicos Podem crescer e encolher conforme a
necessidade
Pearson Education Slide 38
Criando Vetores Dinâmicos Muito simples! Use o operador new
Cria variáveis dinamicamente alocadas Tratadas como vetores
Exemplo:typedef double * DoublePtr;DoublePtr d;d = new double[10];
Cria a variável vetor dinamicamente alocada d,com dez elementos, tipo-base double
Pearson Education Slide 39
Apagando Vetores Dinâmicos Alocados dinamicamente em tempo de execução
Então devem ser apagados em tempo de execução Novamente Simples. Lembre-se do Exemplo:
d = new double[10];… //Processandodelete [] d;
Desaloca toda a memória para o vetor dinâmico Os colchetes indicam que o ‘vetor’ existe Lembre-se: d ainda aponta para lá!
Deve-se fixar d = NULL;
Pearson Education Slide 40
Funções que retornam um vetor Não é permitido que um tipo vetor seja
retornado por uma função. Exemplo:
int [] umaFuncao( ); //ILEGAL Em vez disso retorne um ponteiro para o
tipo-base do vetor:int* umaFuncao( ); //Legal
Pearson Education Slide 41
Aritmética de Ponteiros Pode-se efetuar um tipo de aritmética de
ponteiros
Aritmética de ‘endereços’
Exemplo:typedef double* DoublePtr;
DoublePtr d;
d = new double[10]; d contém o endereço de d[0] d + 1 calcula o endereço de d[1] d + 2 calcula o endereço de d[2]
Pearson Education Slide 42
Manipulação Alternativa de Vetores Use a aritmética de ponteiros! ‘Atravesse’ o vetor sem indexar:
for (int i = 0; i < tamanhoDoVetor; i++)cout << *(d + i)<< " ";
Equivale a:for (int i = 0; i < tamanhoDoVetor; i++)cout << d[i] << " ";
Somente adição/subtração com ponteiros
Não se pode multiplicar nem dividir Pode-se usar ++ e – com ponteiros
Pearson Education Slide 43
Vetores Dinâmicos Multidimensionais Sim, nós podemos! Lembre-se: ‘vetor de vetores’ Uma Definição de tipo ajuda a ‘vê-los’:
typedef int* IntVetorPtr;IntVetorPtr *m = new IntVetorPtr[3];
Cria um vetor de 3 ponteiros Cada um dos quais pode nomear um vetor dinâmico de
ints
for (int i = 0; i < 3; i++)m[i] = new int[4];
O resultado m é um vetor dinâmico de três por quatro.
Pearson Education Slide 44
De volta às Classes O operador ->
Notação Simplificada Combina o operador de desreferenciação, * e
o operador ponto Especifica um membro da classe ‘apontado
por’um dado ponteiro
Exemplo:Registro *p;p = new Registro;p->numero = 2001;p->nota = ’A’;
Pearson Education Slide 45
O Ponteiro this Definições de funções membro podem precisar se referir ao objeto que faz a chamada Use o ponteiro predefinido this
Automaticamente aponta para o objeto que faz a chamada:class Amostra{public:
... void mostraAlgo( ) const;
...private: int algo;
...};
Duas formas para a função membro:cout << algo;cout << this->algo;
Pearson Education Slide 46
Sobrecarregando o Operador de Atribuição
O operador de atribuição retorna uma referência
Assim, atribuíções encadeadas são possíveis
ex.: a = b = c; Fixa a e b igual a c
Operador deve retornar algo de mesmo
tipo que seu lado esquerdo Para garantir que o encadeamento funcione O ponteiro this ajudará com isso!
Pearson Education Slide 47
Sobrecarregando o Operador de Atribuição
Lembre-se: O operador de atribuição deve
ser membro da classe Tem um parâmetro O operando esquerdo é o objeto que chama
s1 = s2; Pense como: s1.=(s2);
s1 = s2 = s3; Requer (s1 = s2) = s3; Então (s1 = s2) deve retornar um objeto do tipo s1
E passar para ‘ = s3’;
Pearson Education Slide 48
Definição do Operador = Sobrecarregado
Exemplo de uso da classe string:
Pearson Education Slide 49
Cópia Rasa e Cópia Profunda Cópia Rasa
Operador de atribuição copia o conteúdo de variáveis-membros de um objeto a outro
Operador de atribuição padrão e o construtorde cópia padrão executam cópias rasas.
Cópia Profunda Ponteiros e Memória dinâmica envolvidos Deve-se desreferenciar variáveis ponteiro
para‘conseguir’ dados para a cópia
Escreva seu próprio operador de atribuição sobrecarregado o construtor de cópia nesse caso!
Pearson Education Slide 50
Destrutores Variáveis dinâmicamente alocadas
Não vão embora até que ‘delete’ seja chamada
Se os ponteiros são somente membors privados
Eles dinâmicamente alocam dados ‘reais’ No construtor
Deve-se ter meios para ‘desalocar’ quando oobjeto for destruído
Resposta: destrutor!
Pearson Education Slide 51
Destrutores Oposto a construtor
Automaticamente chamado quando um objeto
da classe sai do escopo. Versão padrão somente remove variáveis
simples, e não dinâmicas Definido como o construtor, somente adicione ~
MinhaClasse::~MinhaClasse(){
//Responsável pela limpeza}
Pearson Education Slide 52
Construtores de Cópia Automaticamente chamados:
1.Quando um objeto classe é declarado e inicializado por outro objeto
2. Quando a função retorna um valor do tipo classe3. Quando um objeto classe é declarado e inicializado
por outro objeto Requer uma ‘cópia temporária’ do objeto
O construtor de cópia a cria Construtor de cópia padrão
Como padrão só copia o conteúdo de variáveis membro
Pearson Education Slide 53
Sumário 1 Ponteiro é um endereço de memória
Fornece referência indireta à variável Variáveis dinâmicas
Criadas e destruídas enquanto o programa é executado
Pilhas Armazenamento na memória de variáveis
dinâmicas
Vetores alocados dinâmicamente Tamanho determinado enquanto o programa roda
Pearson Education Slide 54
Sumário 2 Destrutor de classe
Função membro especial Destrói objetos automaticamente
Construtor de cópia Função-membro de argumento simples Chamado automaticamente quando uma
cópia temporária é necessária Operador de Atribuição
Deve ser sobrecarregado como uma função-membro
Retorna referência para encadeamento