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 criar 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 gerencie dinamicamente um array de mensagens. A classe deve ter:- Um ponteiro privado para um array de strings alocado dinamicamente
- Um inteiro privado que acompanhe a quantidade atual de mensagens
- Um inteiro privado que armazene a capacidade máxima
- Um construtor que receba uma capacidade e aloque o array usando
new[] - Um destrutor que libere corretamente a memória usando
delete[]e imprima"MessageBox destroyed" - Um método
addMessage(string msg)que adicione uma mensagem se houver espaço, retornandotrueem caso de sucesso oufalsese estiver cheio - Um método
printAll()que imprima cada mensagem armazenada em sua própria linha
main.cpp: leia um valor de capacidade e uma quantidade de mensagens da entrada. Em seguida, leia essa quantidade de strings de mensagem. Crie umMessageBoxno heap usandonew, adicione todas as mensagens a ele, chameprintAll()e então exclua corretamente o MessageBox para liberar a memória.
O formato da entrada será:
- Primeira linha: a capacidade (inteiro)
- Segunda linha: a quantidade 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. Depois de excluir, é uma boa prática definir os ponteiros como nullptr.
Inclua o arquivo de cabeçalho em main.cpp usando #include "MessageBox.h".
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 POO
Arquivos externosBuild e compilação em C++Arquivos de cabeçalho e arquivos-fonteNamespaces e escopoIntrodução à POO em C++Classes vs. objetosO ponteiro 'this'Métodos (funções membro)Atributos (membros de dados)Noções básicas de construtores e destruidoresRevisão - calculadora simples4Propriedades de Classe
Membros de Instância vs. EstáticosGetters e SettersFunções Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRevisão - Gerenciador de Contas Bancárias7Herança
Herança básicaNíveis de acesso da herançaOrdem de chamada de construtor e destrutorSobrescrita de métodosFunções virtuais e VTableHerança múltiplaHerança virtualRevisão - Hierarquia de funcionários10Visão geral da STL
Visão geral e filosofia da STLContêineres da STLIteradoresAlgoritmos da STLFunctors e expressões lambdaRecapitulação - Frequência de palavras13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonFactory e Abstract FactoryPadrão BuilderPadrão ObserverPadrão Strategy2Gerenciamento de Memória
Memória Stack vs. HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Ponteiros Inteligentes em C++RAII em C++Revisão - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de acesso em C++Especificadores de acesso em profundidadeOcultação de informaçõesStruct vs ClasseClasses aninhadas e internasRecapitulação - Sistema de registros de alunos8Polimorfismo
Polimorfismo em compilação vs. execuçãoSobrecarga de funçõesFunções virtuais revisadasFunções virtuais purasClasses abstratasDesign de interfaces em C++Conversão dinâmica e RTTIRecapitulação — Calculadora de formas11Conceitos Avançados de OOP
Composição vs. HerançaMixins via CRTPIdioma PimplApagamento de TiposClasses Enum e Tipagem ForteTratamento de Exceções em OOPHierarquias de Exceções Personalizadas14Padrões de Projeto — Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositeRAII como Padrão3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentoListas de Inicialização do ConstrutorConstrutores DelegantesAprofundamento em DestrutoresRegra dos Três / Cinco / ZeroRevisão - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de FluxoSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçõesTemplates de ClassesEspecialização de TemplatesTemplates VariádicosNoções Básicas de SFINAE e Traits de TiposRecapitulação - Contêiner GenéricoPratique por conta própria: Compilador de C++ online