Menu
Coddy logo textTech

Cópia Profunda

Parte da seção Programação Orientada a Objetos do Journey de C da Coddy. Lição 15 de 61.

Quando você atribui uma struct a outra em C, obtém uma cópia superficial: todos os campos são copiados byte a byte. Isso funciona bem para valores simples, como inteiros, mas cria um problema com ponteiros: ambas as structs acabam apontando para a mesma memória.

typedef struct {
    char *name;
    int age;
} Person;

Person alice = {"Alice", 30};
Person copy = alice;  // Cópia rasa!
// Tanto alice.name quanto copy.name apontam para a MESMA string

Se você liberar um deles, o outro se tornará inválido. Se você modificar a string por meio de um deles, ambos verão a alteração. Isso raramente é o que você deseja.

Uma cópia profunda aloca nova memória para os membros ponteiro e copia os dados reais:

Person *clone_person(const Person *original) {
    Person *copy = malloc(sizeof(Person));
    copy->name = malloc(strlen(original->name) + 1);
    strcpy(copy->name, original->name);
    copy->age = original->age;
    return copy;
}

Agora cada objeto possui sua própria string. Você pode modificar ou liberar uma sem afetar a outra. O padrão é simples: para cada membro ponteiro, aloque memória nova e copie o conteúdo, não apenas o endereço.

challenge icon

Desafio

Fácil

Vamos criar um módulo Student que demonstra o padrão de cópia profunda. Você criará uma função de clonagem que produz uma cópia completamente independente de um objeto estudante: uma cópia na qual modificar ou liberar o original não tem efeito sobre o clone.

Você criará três arquivos:

  • student.h: Declare uma struct Student com dois membros: char *name (uma string alocada dinamicamente) e int grade. Declare três funções:
    • create_student: construtor que recebe um nome e uma nota e retorna um ponteiro para um novo Student
    • clone_student: recebe um const Student * e retorna um ponteiro para uma cópia nova e independente
    • free_student: destrutor que libera corretamente toda a memória alocada
    Use guardas de inclusão com o símbolo STUDENT_H.
  • student.c: Implemente as três funções. Sua função clone_student é a parte principal. Ela deve alocar memória nova tanto para a struct quanto para a string de nome e, em seguida, copiar os dados reais da string (não apenas o endereço do ponteiro). Isso garante que o clone seja totalmente proprietário de sua própria memória, separada da memória do original.
  • main.c: Crie um estudante, clone-o, exiba as informações de ambos os estudantes e, em seguida, limpe corretamente os dois objetos.

Você receberá duas entradas: o nome do estudante (uma string) e a nota (um inteiro).

Em seu arquivo principal, crie um estudante com os valores fornecidos e, em seguida, crie um clone desse estudante. Imprima as informações do original e do clone para verificar se eles contêm os mesmos dados. Por fim, libere os dois estudantes e imprima uma confirmação.

Imprima a saída neste formato:

Original: {name}, Grade: {grade}
Clone: {name}, Grade: {grade}
Both freed

Por exemplo, com as entradas Alice e 95, a saída seria:

Original: Alice, Grade: 95
Clone: Alice, Grade: 95
Both freed

O padrão de cópia profunda garante que cada objeto seja realmente independente: o clone tem sua própria string alocada, e não um ponteiro compartilhado para a memória do original.

Experimente você mesmo

#include <stdio.h>
#include <stdlib.h>
#include "student.h"

int main() {
    char name[100];
    int grade;
    
    // Ler entrada
    scanf("%s", name);
    scanf("%d", &grade);
    
    // TODO: Crie um estudante com o nome e a nota fornecidos
    
    // TODO: Crie um clone do estudante
    
    // TODO: Print the original student's information
    // Formato: "Original: {name}, Grade: {grade}"
    
    // TODO: Imprima as informações do clone
    // Formato: "Clone: {name}, Grade: {grade}"
    
    // TODO: Liberar ambos os estudantes
    
    // Imprimir confirmação
    printf("Both freed\n");
    
    return 0;
}
quiz iconTeste seus conhecimentos

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

Pratique por conta própria: Compilador de C online