Memória Dinâmica (new/delete)
Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 14 de 104.
Agora que você entende ponteiros e referências, vamos colocá-los em prática com alocação dinâmica de memória. Os operadores new e delete permitem que você crie e destrua objetos no heap em tempo de execução.
Use new para alocar memória e obter um ponteiro para ela:
int* num = new int; // Aloca um único inteiro
*num = 42; // Atribui valor através do ponteiro
Player* player = new Player("Hero"); // Aloca um objetoCada new deve ter um delete correspondente para liberar a memória:
delete num; // Libera um único objeto
delete player; // Chama o destrutor e, em seguida, libera a memóriaPara arrays, use new[] e delete[]:
int* scores = new int[5]; // Aloca um array de 5 inteiros
scores[0] = 100;
delete[] scores; // Libera o array - note os colchetes!Erros comuns a serem evitados:
// Vazamento de memória - esqueceu de deletar
int* ptr = new int(10);
ptr = new int(20); // Perdeu o acesso à primeira alocação!
// Ponteiro pendente - usando após deletar
delete ptr;
*ptr = 5; // Comportamento indefinido!
// Delete incompatível
int* arr = new int[10];
delete arr; // Errado! Deveria ser delete[]Após a exclusão, defina os ponteiros como nullptr para evitar o reuso acidental. O gerenciamento manual de memória é propenso a erros, razão pela qual o C++ moderno prefere ponteiros inteligentes, que exploraremos a seguir.
Desafio
FácilVamos construir um sistema simples de armazenamento de mensagens que demonstra a alocação dinâmica de memória com new e delete.
Você criará dois arquivos para organizar seu código:
MessageBox.h: Defina uma classeMessageBoxque gerencia dinamicamente um array de mensagens. A classe deve ter:- Um ponteiro privado para um array de strings alocado dinamicamente
- Um inteiro privado que rastreia a contagem atual de mensagens
- Um inteiro privado que armazena a capacidade máxima
- Um construtor que recebe uma capacidade e aloca o array usando
new[] - Um destrutor que libera adequadamente a memória usando
delete[]e imprime"MessageBox destroyed" - Um método
addMessage(string msg)que adiciona uma mensagem se houver espaço, retornandotrueem caso de sucesso oufalsese estiver cheio - Um método
printAll()que imprime cada mensagem armazenada em sua própria linha
main.cpp: Leia um valor de capacidade e um número de mensagens da entrada. Em seguida, leia essa quantidade de strings de mensagem. Crie umMessageBoxna heap usandonew, adicione todas as mensagens a ele, chameprintAll()e, em seguida, delete adequadamente o MessageBox para liberar memória.
O formato de entrada será:
- Primeira linha: a capacidade (inteiro)
- Segunda linha: o número de mensagens a adicionar (inteiro)
- Linhas seguintes: uma mensagem por linha
Lembre-se: cada new precisa de um delete correspondente, e cada new[] precisa de um delete[] correspondente. Após deletar, é uma boa prática definir os ponteiros como nullptr.
Inclua seu arquivo de cabeçalho no main.cpp usando #include "MessageBox.h".
Folha de consulta
Use new para alocar memória dinamicamente no heap e obter um ponteiro para ela:
int* num = new int; // Allocate single integer
*num = 42; // Assign value through pointer
Player* player = new Player("Hero"); // Allocate objectTodo new deve ter um delete correspondente para liberar a memória:
delete num; // Free single object
delete player; // Calls destructor, then frees memoryPara arrays, use new[] e delete[]:
int* scores = new int[5]; // Allocate array of 5 integers
scores[0] = 100;
delete[] scores; // Free array - note the brackets!Erros comuns a evitar:
// Memory leak - forgot to delete
int* ptr = new int(10);
ptr = new int(20); // Lost access to first allocation!
// Dangling pointer - using after delete
delete ptr;
*ptr = 5; // Undefined behavior!
// Mismatched delete
int* arr = new int[10];
delete arr; // Wrong! Should be delete[]Após deletar, defina os ponteiros como nullptr para evitar o reuso acidental.
Experimente você mesmo
#include <iostream>
#include <string>
#include "MessageBox.h"
using namespace std;
int main() {
int capacity;
int numMessages;
// Lê a capacidade e o número de mensagens
cin >> capacity;
cin >> numMessages;
cin.ignore(); // Limpa a nova linha após o número
// TODO: Criar um MessageBox no heap usando new
// TODO: Ler e adicionar todas as mensagens ao MessageBox
for (int i = 0; i < numMessages; i++) {
string message;
getline(cin, message);
// Adiciona a mensagem ao MessageBox
}
// TODO: Chamar printAll() para exibir todas as mensagens
// TODO: Deletar o MessageBox para liberar memória
// Lembre-se de definir o ponteiro como nullptr após deletar
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP
Arquivos ExternosBuild e Compilação em C++Arquivos Header e SourceNamespaces e EscopoIntrodução a OOP em C++Classes vs ObjetosO Ponteiro 'this'Métodos (Funções Membro)Atributos (Membros de Dados)Básico de Ctors e DtorsRecapitulação - Calculadora Simples4Propriedades de Classe
Membros de Instância vs EstáticosGetters e SettersFunções de Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRecapitulação - Gerenciador de Conta Bancária7Herança
Herança BásicaNíveis de Acesso na HerançaOrdem de Chamada de Ctor e DtorSobrescrita de MétodosFunções Virtuais e VTableHerança MúltiplaHerança VirtualRecapitulação - Hierarquia de Funcionários2Gerenciamento de Memória
Memória Stack vs HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Smart Pointers em C++RAII em C++Recapitulação - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de Acesso em C++Especificadores de Acesso em DetalhesOcultação de InformaçãoStruct vs ClassClasses Aninhadas e InternasRecapitulação - Sistema de Registros de Alunos8Polimorfismo
Polimorfismo de Compilação vs Tempo de ExecuçãoSobrecarga de FunçõesFunções Virtuais RevisitadasFunções Virtuais PurasClasses AbstratasDesign de Interfaces em C++Dynamic Casting e RTTIRecapitulação - Calculadora de Formas3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentaçãoListas de Inicialização do ConstrutorConstrutores DelegadosMergulho Profundo em DestrutoresRegra dos Três / Cinco / ZeroRecapitulação - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de StreamSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçãoTemplates de ClasseEspecialização de TemplatesTemplates VariádicosFundamentos de SFINAE e Type TraitsRecapitulação - Container Genérico