Fácil C++
Implemente o construtor de cópia
Enunciado
Complete a classe String para que o construtor de cópia faça uma cópia profunda da string alocada dinamicamente. O programa deve imprimir o conteúdo das duas strings e não deve causar double free.
Requisitos
- O construtor de cópia aloca nova memória e copia o conteúdo.
- O destrutor libera a memória corretamente.
- A saída mostra as duas strings iguais.
Código inicial
#include <iostream>
#include <cstring>
class String {
char* data_;
public:
String(const char* s) {
data_ = new char[std::strlen(s) + 1];
std::strcpy(data_, s);
}
// TODO: construtor de cópia
~String() { delete[] data_; }
const char* c_str() const { return data_; }
};
int main() {
String a("hello");
String b = a;
std::cout << a.c_str() << " " << b.c_str() << "\n";
return 0;
}
Saída esperada
hello hello
Ver dica
No construtor de cópia, aloque new char[std::strlen(other.data_) + 1] e copie com std::strcpy.
Mostrar solução
#include <iostream>
#include <cstring>
class String {
char* data_;
public:
String(const char* s) {
data_ = new char[std::strlen(s) + 1];
std::strcpy(data_, s);
}
// Construtor de cópia: cópia profunda
String(const String& other) {
data_ = new char[std::strlen(other.data_) + 1];
std::strcpy(data_, other.data_);
}
~String() { delete[] data_; }
const char* c_str() const { return data_; }
};
int main() {
String a("hello");
String b = a;
std::cout << a.c_str() << " " << b.c_str() << "\n";
return 0;
}
Passo a passo
- A classe
Stringguarda um ponteirochar* data_para uma string alocada dinamicamente. - O construtor comum aloca memória e copia o literal.
- O construtor de cópia recebe
const String& othere aloca um novo buffer do mesmo tamanho. - Em seguida, copia o conteúdo com
std::strcpy, garantindo que cada objeto tenha sua própria memória. - O destrutor libera a memória de cada objeto independentemente.
- No
main,String b = a;chama o construtor de cópia, criando uma cópia profunda.
Por que funciona
Sem o construtor de cópia, o compilador geraria uma cópia superficial que apenas copiaria o ponteiro. Assim, a e b apontariam para o mesmo buffer, e o destrutor seria chamado duas vezes, causando double free. O construtor de cópia personalizado resolve isso alocando memória separada.
Erros comuns
- Esquecer de alocar memória:
data_ = other.data_;causa cópia superficial e double free. - Não copiar o terminador nulo: usar
new char[strlen(other.data_)]sem+1leva a buffer overflow. - Não tratar auto-atribuição: se
this == &other, a cópia pode liberar a memória antes de copiar.
Outra forma de resolver
Usar std::string da biblioteca padrão, que já implementa cópia profunda corretamente:
#include <string>
std::string a = "hello";
std::string b = a;
Saída esperada
hello hello