Baixe o app para aproveitar ainda mais
Prévia do material em texto
Laboratório de Programação II Departamento de Ciência da Computação UFJF Aula de hoje • Alocação dinâmica de memória • Operadores new e delete • Alocação dinâmica de vetores e matrizes • Alocação dinâmica de estruturas • Estática – onde variáveis globais e estáticas (static) são armazenadas • Heap – alocada dinamicamente em tempo de execução - memória “manuseável” acessada através do uso de ponteiros • Pilha – usada automaticamente pelas variáveis locais Em C e C++, existem três tipos de memória usadas pelos programas: Alocação dinâmica de memória • Quando um programa é executado, a memória do processo é dividida em quatro áreas: – Instruções – armazena o código C compilado e montado em linguagem de máquina; – Pilha – nela são criadas as variáveis locais; – Memória estática – onde são criadas as variáveis globais e locais estáticas; – Heap – destinado a armazenar dados alocados dinamicamente. Alocação dinâmica de memória Alocação dinâmica de memória Embora seu tamanho seja desconhecido, o heap geralmente contém uma quantidade razoavelmente grande de memória livre. • As variáveis da pilha e da memória estática precisam ter tamanho conhecido antes do programa ser compilado. • A alocação dinâmica de memória permite reservar espaços de memória de tamanho arbitrário e acessá-los através de ponteiros. • Desta forma, podemos escrever programas mais flexíveis, pois nem todos os tamanhos devem ser definidos ao escrever o programa. Alocação dinâmica de memória • Em C, a alocação e liberação desses espaços de memória é feita pelas funções malloc() e free() – malloc(): aloca memória – free(): libera memória • Em C++ isto é feito usando os operadores new e delete Alocação dinâmica de memória • new é usado para alocar memória em tempo de execução – aloca um bloco de bytes consecutivos na memória – retorna um ponteiro para o endereço de onde um objeto pode ser armazenado – sempre retorna um ponteiro para o tipo que segue o operador new Operador new Sintaxe do operador new new TipoDeDado new TipoDeDado [Tamanho] • Se existir memória disponível na heap, o operador new aloca memória suficiente para uma variável do TipoDeDado ou para um array deste tipo, e retorna um ponteiro para (endereço da) área de memória alocada • Caso contrário, o programa termina automaticamente com uma mensagem de erro. • O objeto alocado dinamicamente existe até que o operador delete seja usado para destruí-lo. char * ptr; ptr = new char; *ptr = ‘H’; cout << *ptr; 200 ??? ptr 500 500 ‘H’ Operador new Operador new #include <iostream> using namespace std; int main() { int num = 101; int * pt = new int; // aloca espaco p/ int *pt = 202; // armazena um valor cout << “valor de num = “ << num; cout << ": endereco " << &num << endl; cout << “valor do int = “ << *pt; cout << ": endereco = " << pt << endl; // continua Operador new // continua double * pd = new double; *pd = 10000001.0; cout << "valor do double =" << *pd; cout << ": endereco = " << pd << endl; cout << "endereco do ponteiro pd: “; cout << &pd << endl; return 0; } Operador delete • Libera o uso de um bloco de memória, permitindo que este espaço seja reaproveitado. • O operador delete deve ser usado com um endereço de memória que foi originalmente alocado com o operador new. • É recomendado que o uso do new seja sempre balanceado com o uso do delete, caso contrário você estará perdendo memória que poderia ser usada. Operador delete • Atenção: – Você não deve tentar usar o delete para liberar memória que já foi previamente desalocada. O resultado dessa operação é indefinido. – Você não deve usar o delete para liberar memória de uma variável ordinária que não foi alocada dinamicamente. • Ou seja, não é possível desalocar memória que não foi alocada, assim como não é possível desalocar o mesmo bloco de memória duas vezes. Operador delete delete Ponteiro delete [] Ponteiro • O objeto ou array apontado por Ponteiro é desalocado e o seu valor passa a ser indefinido. A memória é disponibilizada para uso novamente na heap. • Colchetes [] são usados para desalocar memória de um array alocado dinamicamente. Operador delete char *ptLetra; ptLetra = new char; // aloca *ptLetra = ‘B’; cout << “Valor do caracter = “ << *ptLetra; delete ptLetra; // desaloca OBS: o delete desaloca a memória apontada por ptLetra, mas não desaloca a memória de ptLetra. Ou seja, podemos reutilizar esse ponteiro. Alocando e desalocando arrays • Até então usamos o new e delete para alocar variáveis ordinárias. Vamos ver como alocar um array de elementos do mesmo tipo. • Basta usar os comandos: – new tipo[tamanho]; – delete [] ponteiro; – onde tamanho é um número inteiro, tipo o nome de um tipo de dados (int,float…) e ponteiro é o ponteiro retornado pelo new. Alocando e desalocando arrays int i; float *dados; dados = new float[5]; // aloca for(i=0; i<5; i++) { dados[i] = (i+1)*(i+1); cout << “valor de dados[i]=“ << dados[i]; cout << endl; } delete [] dados; // desaloca Alocando e desalocando arrays int i, N; float *dados; cin >> N; dados = new float[N]; for(i=0; i<N; i++) { dados[i] = (i+1)*(i+1); cout << “valor de dados[i]=“ << dados[i]; cout << endl; } delete [] dados; // desaloca Observe, que como se trata de alocação dinâmica, podemos determinar a quantidade de memória (no caso o tamanho do array) a alocar em tempo de execução e alocar um array com o tamanho especificado pelo usuário. Alocando e desalocando arrays int i, N; float *dados; dados = new float[N]; // ... faz alguma coisa delete [] dados; dados = new float[10]; // ... faz alguma outra coisa delete [] dados; dados = new float; // ... delete dados; Lembre-se, o operador delete desaloca apenas a memória apontada pelo ponteiro, mas não a memória da variável do tipo ponteiro. Podemos utilizar novamente o ponteiro. Operadores new e delete • Alocou memória com: new tipo; • Desaloca com: delete pt; • Alocou memória com: new tipo[tam]; • Desaloca com: delete [] pt; Alocação de memória • Também podemos fazer alocação dinâmica de memória dentro de funções. float * somaVetores(float u[], float v[]) { float *r = new float[3]; r[0] = u[0] + v[0]; r[1] = u[1] + v[1]; r[2] = u[2] + v[2]; return r; } Alocação de memória int i, dim=3; float vecU[3] = {1.0,1.0,1.0}; float vecV[3] = {2.0,1.0,-1.0}; float *vecResultado; // aloca um array e calcula soma vecResultado = somaVetores(vecU, vecV); for(i=0; i<dim; i++){ cout << “resultado “ << i << “ = “; cout << vecResultado[i] << endl; } delete [] vecResultado; Alocação de memória • Estática int meuArray[10]; meuArray[3] = 99; • Dinâmica int *ptr; ptr = new int[10]; ptr[3] = 99; // ou *(ptr+3) = 99; Alocando estruturas • Considere a seguinteestrutura: • Vamos ver um exemplo de como alocar memória de forma dinâmica para tipos de dados definidos pelo programador. struct ponto_t { float x; float y; }; typedef struct ponto_t Ponto; Alocando estruturas (Exemplo 1) Ponto *pt; pt = new Ponto; cout << “Digite as coordenadas X Y: “; cin >> pt->x; cin >> pt->y; cout << “Coordenadas “; cout << “X = “ << pt->x << endl; cout << “Y = “ << pt->y << endl; delete pt; Alocando estruturas (Exemplo 2) Ponto * lePonto(){ Ponto *pt; pt = new Ponto; cout << "Digite o ponto:"; cin >> pt->x >> pt->y; return pt; } float calcDistancia(Ponto *pt1, Ponto *pt2) { float d,dx,dy,dz; dx = pt2->x - pt1->x; dy = pt2->y - pt1->y; d = sqrt(dx*dx + dy*dy); return d; } int main() { float d; Ponto *pt1, *pt2; pt1 = lePonto(); pt2 = lePonto(); d=calcDistancia(pt1,pt2); cout << "Distancia= "; cout << dist << endl; delete pt1; delete pt2; return 0; } Exercícios 1. Faça um programa que leia um número N e aloque um vetor com N inteiros de forma dinâmica (use o operador new). Em seguida o programa deve calcular a média dos elementos desse vetor, e por fim, deve desalocar (use o operador delete) a memória alocada para armazenar os seus elementos. 2. Implemente uma função que calcule o produto escalar entre dois vetores do tipo de dados float. No programa principal você deve ler o tamanho N dos vetores, os quais devem ser alocados dinamicamente usando new. Depois você deve ler os dados dos vetores e chamar a função para calcular o produto escalar. Por fim, use o operador delete para desalocar toda memória alocada de forma dinâmica. float prodEscalar(int n, float u[], float v[]); Exercícios Exercícios 3. Considere o tipo Ponto definido no exemplo. Implemente as seguintes funções a seguir e faça uso das mesmas no programa principal: void altera(Ponto *p, float xx, float yy); void imprime(Ponto *p); bool iguais(Ponto *p1, Ponto *p2); Dica: reaproveite o código do exemplo para fazer o exercício.
Compartilhar