C++ 101 – Parte 6 – Dynamic Memory Allocation e o Crivo de Eratóstenes (outra vez)

Posted on 08/10/2011

0


Olá pessoal, tudo certo?!

O post de hoje começa a “separar os meninos dos homens”. Hoje, começo a falar sobre como funciona a alocação dinâmica (em tempo de execução) de memória.

Diferente do que encontramos em linguagens .NET, onde temos um “garbage collector” cuidando da liberação da memória que utilizamos e que não é mais necessária, em C++ fazemos esse controle “na unha”. Se, por um lado, aumentamos a complexidade, por outro, temos mais controle sobre o que está, de fato, acontecendo.

Se está chegando agora, considere ver os outros posts dessa série.

Por que é necessário saber fazer alocação dinâmica?

Quando declaramos variáveis e especificamos seus tipos estamos, de fato, determinando a quantidade de memória que será necessária para a execução do programa. Tudo isso, em tempo de compilação. Entretanto, frequentemente necessitamos decidir a quantidade de memória que precisará ser alocada em run-time, dependendo, por exemplo, dos inputs dos usuários.

Qualquer programa que faça algum tipo de “carga” e processamento de um conjunto de dados de tamanho desconhecido durante a escrita do código precisará alocar memória para armazenamento em tempo de execução.

Em C++, quando “alocamos” memória dinâmicamente, obtemos um “endereço” de memória que mantemos com um ponteiro.

O que é o Heap?

Durante a execução de nossos programas, há uma quantidade de memória disponível. Ou seja, memória no computador que não está sendo utilizada por outros programas. Essa memória “livre” é conhecida como heap.

Como alocar algum espaço no heap?

Em C++, alocamos algum espaço no heap utilizando o operador new. Quando não desejamos mais utilizar essa memória, liberamos utilizando o operador delete. Considere:


              
#include ;

using std::cout;
using std::endl;

void main()
{
        double *pvalue = nullptr;
        // aloca espaço no heap para um valor double
        pvalue = new double;

        *pvalue = 5;
        cout << "Valor de pvalue : " << pvalue << endl
                 << "Valor de *pvalue: " << *pvalue << endl;

        // libera o espaço alocado
        delete pvalue;
}

            

Executando …

image

Acho que o código é simples de entender.

Obviamente, podemos alocar a memória e atribuir o valor em uma única linha. Observe:


              
#include ;

using std::cout;
using std::endl;

void main()
{
        // aloca espaço no heap para um valor double
        double *pvalue = new double(5);

        cout << "Valor de pvalue : " << pvalue << endl
                 << "Valor de *pvalue: " << *pvalue << endl;

        // libera o espaço alocado
        delete pvalue;
}

            

Importante: Sempre que memória alocada não for mais necessária deverá ser, obrigatoriamente, liberada com delete.

Se isso não feito, a memória permanecerá alocada até o fim da execução do programa.

Alocando memória dinamicamente para Arrays

No post anterior, mostrei como criar arrays com tamanho fixo (determinado durante a escrita do código). Agora, é hora de ver como fazer isso em tempo de execução. Considere:


              
void main()
{
        char* pstring = new char[50];
        delete [] pstring;
}

            

A primeira linha, aloca um “array” com 50 chars em memória. A segunda, libera a memória alocada. Repare a utilização dos colchetes junto a instrução delete. Isso indica que estamos removendo um array.

Abaixo, segue uma implementação do “crivo de Eratóstenes” que pede ao usuário o “limite máximo”. Observe:


              
#include ;

using std::cout;
using std::cin;
using std::endl;

void main()
{

        int n = 0;
        cout << "Informe limite superior para primos: ";
        cin >> n;

        long i;
        int* pvalues = new int[n];
        for (i = 2; i < n; i++) pvalues[i] = 1;

        for (i = 2; i < n; i++)
                if (pvalues[i])
                        for (int j = i; (j * i) < n; j++)
                                pvalues[i * j] = 0;

        for (i = 2; i < n; i++)
                if (pvalues[i])
                        cout << " " << i;

        cout << endl;

        delete [] pvalues;
}

            

Resultado:

image

Bacana!

Era isso!

Smiley piscando

Etiquetado:,
Posted in: C++