Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> Linguagem C

Dominando Memória Dinâmica em C++: Stack vs Heap Explicados

Uma boa compreensão de como a memória dinâmica realmente funciona em C++ é essencial para se tornar um bom programador C++. A memória no seu programa C++ é dividida em duas partes:

Muitas vezes, você não sabe antecipadamente quanta memória precisará para armazenar informação particular em uma variável definida e o tamanho da memória necessária pode ser determinado em tempo de execução.

Você pode alocar memória em tempo de execução dentro da heap para a variável de um tipo dado usando um operador especial em C++ que retorna o endereço do espaço alocado. Este operador é chamado de operador new.

Se você não precisa mais de memória alocada dinamicamente, pode usar o operador delete, que desaloca memória previamente alocada pelo operador new.

Operadores new e delete

Existe a seguinte sintaxe genérica para usar o operador new para alocar memória dinamicamente para qualquer tipo de dado:

new data-type;

Aqui, data-type pode ser qualquer tipo de dado embutido incluindo array ou qualquer tipo de dado definido pelo usuário incluindo classe ou estrutura. Vamos começar com tipos de dados embutidos. Por exemplo, podemos definir um ponteiro para tipo double e então requisitar que a memória seja alocada em tempo de execução. Podemos fazer isso usando o operador new com as seguintes instruções:

double* pvalue = NULL; // Ponteiro inicializado com null
pvalue = new double;   // Requisição de memória para a variável

A memória pode não ter sido alocada com sucesso, se o free store tiver sido usado. Então é boa prática verificar se o operador new está retornando ponteiro NULL e tomar ação apropriada como abaixo:

double* pvalue = NULL;
if(!(pvalue = new double)) {
    cout << "Error: out of memory." << endl;
    exit(1);
}

A função malloc() do C ainda existe em C++, mas é recomendado evitar usar malloc(). A principal vantagem do new sobre malloc() é que new não apenas aloca memória, ele constrói objetos, que é o propósito principal do C++.

A qualquer momento, quando você sentir que uma variável alocada dinamicamente não é mais necessária, pode liberar a memória que ela ocupa no free store com o operador 'delete' da seguinte forma:

delete pvalue; // Libera memória apontada por pvalue

Vamos juntar os conceitos acima e formar o exemplo a seguir para mostrar como 'new' e 'delete' funcionam:

#include <iostream>
using namespace std;
int main() {
    double* pvalue = NULL; // Ponteiro inicializado com null
    pvalue = new double;   // Requisição de memória para a variável
    *pvalue = 29494.99;    // Armazena valor no endereço alocado
    cout << "Value of pvalue: " << *pvalue << endl;
    delete pvalue;         // Libera a memória
    return 0;
}

Se compilarmos e executarmos o código acima, isso produziria o seguinte resultado:

Value of pvalue: 29495

Alocação Dinâmica de Memória para Arrays

Considere que você queira alocar memória para um array de caracteres, ou seja, string de 20 caracteres. Usando a mesma sintaxe que usamos acima, podemos alocar memória dinamicamente como mostrado abaixo:

char* pvalue = NULL;        // Ponteiro inicializado com null
pvalue = new char[20];      // Requisição de memória para a variável

Para remover o array que acabamos de criar, a instrução seria assim:

delete[] pvalue; // Deleta array apontado por pvalue

Seguindo a sintaxe genérica similar do operador new, você pode alocar para um array multi-dimensional da seguinte forma:

double** pvalue = NULL;         // Ponteiro inicializado com null
pvalue = new double[3][4];      // Aloca memória para array 3x4

No entanto, a sintaxe para liberar memória para array multi-dimensional permanece a mesma:

delete[] pvalue; // Deleta array apontado por pvalue

Alocação Dinâmica de Memória para Objetos

Objetos não são diferentes de tipos de dados simples. Por exemplo, considere o seguinte código onde vamos usar um array de objetos para esclarecer o conceito:

#include <iostream>
using namespace std;
class Box {
public:
    Box() { cout << "Constructor called!" << endl; }
    ~Box() { cout << "Destructor called!" << endl; }
};
int main() {
    Box* myBoxArray = new Box[4];
    delete[] myBoxArray; // Deleta array
    return 0;
}

Se você alocar um array de quatro objetos Box, o construtor simples será chamado quatro vezes e similarmente ao deletar esses objetos, o destrutor também será chamado o mesmo número de vezes.

Se compilarmos e executarmos o código acima, isso produziria o seguinte resultado:

Constructor called!
Constructor called!
Constructor called!
Constructor called!
Destructor called!
Destructor called!
Destructor called!
Destructor called!

Linguagem C

  1. Entendendo Tipos de Dados em C++: Fundamentos, Modificadores e Boas Práticas
  2. Dominando Operadores em C++: Guia Completo com Exemplos Práticos
  3. Comentários em C++: Boas Práticas para Código Legível e Manutenível
  4. Gerenciamento Dinâmico de Memória em C: calloc, malloc e free Explicados
  5. Linguagem de Programação C++: Visão Geral e Principais Características
  6. Constantes e Literais em C++: Tipos, Sintaxe e Boas Práticas
  7. Guia Completo de Operadores em C++: Tipos, Uso e Boas Práticas
  8. Dominando Tipos Numéricos em C++: Guia Prático
  9. Entendendo Referências em C++: Conceitos-Chave e Diferenças de Ponteiros
  10. Dominando Memória Dinâmica em C++: Stack vs Heap Explicados