Desafio C++
Gerenciamento de recurso com construtor e destrutor
Enunciado
Implemente uma classe Buffer que gerencia um array dinâmico de inteiros. Ela deve:
- Ter um construtor padrão que cria um buffer vazio (tamanho 0).
- Ter um construtor
explicitque recebe um tamanho e aloca memória dinamicamente. - Ter um destrutor que libera a memória alocada.
- Ter um método
set(int indice, int valor)que define um valor em uma posição. - Ter um método
get(int indice) constque retorna o valor em uma posição. - Ter um método
tamanho() constque retorna o tamanho do buffer.
No main, crie um Buffer com tamanho 5, preencha com valores de 0 a 4, mostre os valores e o tamanho. Depois crie um Buffer padrão e mostre seu tamanho.
Requisitos
- O construtor com tamanho deve alocar memória com
new int[tamanho]. - O destrutor deve liberar a memória com
delete[]. - Os métodos
setegetdevem acessar posições válidas (assuma que o índice é válido). - O programa deve exibir
Buffer: 0 1 2 3 4eTamanho: 5eBuffer padrao tamanho: 0.
Código inicial
#include <iostream>
class Buffer {
public:
// TODO: construtor padrão
// TODO: construtor explicit com tamanho
// TODO: destrutor
void set(int indice, int valor) { /* TODO */ }
int get(int indice) const { /* TODO */ }
int tamanho() const { /* TODO */ }
private:
int* dados_;
int tamanho_;
};
int main() {
// TODO: criar Buffer(5), preencher e mostrar
// TODO: criar Buffer padrão e mostrar tamanho
return 0;
}
Saída esperada
Buffer: 0 1 2 3 4
Tamanho: 5
Buffer padrao tamanho: 0
Ver dica
No construtor padrão, inicialize dados_ como nullptr e tamanho_ como 0. No construtor com tamanho, aloque com new int[tamanho] e inicialize os elementos se necessário. No destrutor, use delete[] dados_.
Mostrar solução
#include <iostream>
class Buffer {
public:
// Construtor padrão: buffer vazio
Buffer() : dados_(nullptr), tamanho_(0) {}
// Construtor explícito: aloca array de inteiros
explicit Buffer(int tamanho) : dados_(new int[tamanho]), tamanho_(tamanho) {
// Inicializa com zeros (opcional)
for (int i = 0; i < tamanho_; ++i) {
dados_[i] = 0;
}
}
// Destrutor: libera memória
~Buffer() {
delete[] dados_;
}
void set(int indice, int valor) {
dados_[indice] = valor;
}
int get(int indice) const {
return dados_[indice];
}
int tamanho() const {
return tamanho_;
}
private:
int* dados_;
int tamanho_;
};
int main() {
Buffer buf(5);
for (int i = 0; i < buf.tamanho(); ++i) {
buf.set(i, i);
}
std::cout << "Buffer: ";
for (int i = 0; i < buf.tamanho(); ++i) {
std::cout << buf.get(i) << (i < buf.tamanho() - 1 ? " " : "\n");
}
std::cout << "Tamanho: " << buf.tamanho() << "\n";
Buffer padrao;
std::cout << "Buffer padrao tamanho: " << padrao.tamanho() << "\n";
return 0;
}
Passo a passo
- A classe
Buffertem dois membros privados:dados_(ponteiro para int) etamanho_(int). - O construtor padrão inicializa
dados_comonullptretamanho_como 0, representando um buffer vazio. - O construtor
explicit Buffer(int tamanho)aloca um array dinâmico comnew int[tamanho]e inicializa todos os elementos com 0. - O destrutor
~Buffer()libera a memória alocada comdelete[] dados_. É crucial para evitar vazamentos de memória. - O método
setatribui um valor a uma posição do array. - O método
getretorna o valor de uma posição. tamanho()retorna o tamanho do buffer.- No
main, criamosBuffer buf(5), preenchemos comie imprimimos os valores. Depois criamosBuffer padraoe mostramos seu tamanho.
Por que funciona
O construtor com tamanho aloca memória dinamicamente e o destrutor a libera, seguindo o princípio RAII (Resource Acquisition Is Initialization). O construtor padrão cria um buffer vazio sem alocar memória, e o destrutor lida com nullptr sem problemas (delete[] em nullptr é seguro). O explicit impede conversões implícitas de int para Buffer.
Erros comuns
- Esquecer de liberar a memória no destrutor:
~Buffer() {}causa vazamento de memória. - Usar
deleteem vez dedelete[]para um array alocado comnew[]:delete dados_;é comportamento indefinido. Usedelete[]. - Não inicializar
dados_no construtor padrão: se não for inicializado, o destrutor pode tentar liberar memória inválida. Inicialize comnullptr. - Tentar copiar um
Buffersem definir construtor de cópia: a cópia padrão copia o ponteiro, levando a double free. Para este exercício, não é necessário, mas é bom saber.
Outra forma de resolver
Usar std::vector<int> em vez de ponteiro bruto, eliminando a necessidade de destrutor manual. No entanto, o objetivo aqui é praticar gerenciamento manual de recursos.
Saída esperada
Buffer: 0 1 2 3 4
Tamanho: 5
Buffer padrao tamanho: 0