Menu
Coddy logo textTech

Kopia głęboka

Część sekcji Programowanie obiektowe ścieżki C w Coddy. Lekcja 15 z 61.

Gdy przypisujesz jedną strukturę do drugiej w C, otrzymujesz kopię płytką: wszystkie pola są kopiowane bajt po bajcie. To działa dobrze w przypadku prostych wartości, takich jak liczby całkowite, ale powoduje problem ze wskaźnikami: obie struktury wskazują ostatecznie na tę samą pamięć.

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

Person alice = {"Alice", 30};
Person copy = alice;  // Kopia płytka!
// Zarówno alice.name, jak i copy.name wskazują na TEN SAM ciąg znaków

Jeśli zwolnisz jeden z nich, drugi stanie się nieprawidłowy. Jeśli zmodyfikujesz ciąg znaków za pomocą jednego, zmiana będzie widoczna w obu. Rzadko kiedy tego chcesz.

Głęboka kopia przydziela nową pamięć dla składowych będących wskaźnikami i kopiuje rzeczywiste dane:

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;
}

Teraz każdy obiekt ma własny ciąg znaków. Możesz go zmodyfikować lub zwolnić bez wpływu na drugi. Wzorzec jest prosty: dla każdego składowego wskaźnika przydziel nową pamięć i skopiuj zawartość, a nie tylko adres.

challenge icon

Wyzwanie

Łatwy

Zbudujmy moduł Student, który demonstruje wzorzec głębokiego kopiowania. Utworzysz funkcję klonującą, która tworzy całkowicie niezależną kopię obiektu studenta: taką, w której modyfikowanie lub zwalnianie oryginału nie ma wpływu na klon.

Utworzysz trzy pliki:

  • student.h: Zadeklaruj strukturę Student z dwoma polami: char *name (dynamicznie alokowany ciąg znaków) oraz int grade. Zadeklaruj trzy funkcje:
    • create_student: konstruktor, który przyjmuje imię i ocenę oraz zwraca wskaźnik do nowego obiektu Student
    • clone_student: przyjmuje const Student * i zwraca wskaźnik do nowej, niezależnej kopii
    • free_student: destruktor, który prawidłowo zwalnia całą zaalokowaną pamięć
    Użyj strażników dołączania z symbolem STUDENT_H.
  • student.c: Zaimplementuj wszystkie trzy funkcje. Kluczowa jest funkcja clone_student. Musi zaalokować nową pamięć zarówno dla struktury, jak i ciągu znaków z imieniem, a następnie skopiować dane samego ciągu (a nie tylko adres wskaźnika). Dzięki temu klon będzie miał własną pamięć, całkowicie oddzieloną od pamięci oryginału.
  • main.c: Utwórz obiekt studenta, sklonuj go, wyświetl informacje o obu obiektach, a następnie prawidłowo zwolnij oba.

Otrzymasz dwa dane wejściowe: imię studenta (ciąg znaków) i ocenę (liczbę całkowitą).

W pliku głównym utwórz obiekt studenta z podanych wartości, a następnie utwórz jego klon. Wypisz informacje o oryginale i klonie, aby sprawdzić, czy zawierają te same dane. Na koniec zwolnij oba obiekty i wypisz potwierdzenie.

Wypisz dane wyjściowe w tym formacie:

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

Na przykład dla danych wejściowych Alice i 95 dane wyjściowe będą następujące:

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

Wzorzec głębokiego kopiowania zapewnia, że każdy obiekt jest naprawdę niezależny: klon ma własny zaalokowany ciąg znaków, a nie współdzielony wskaźnik do pamięci oryginału.

Spróbuj swoich sił

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

int main() {
    char name[100];
    int grade;
    
    // Wczytaj dane wejściowe
    scanf("%s", name);
    scanf("%d", &grade);
    
    // TODO: Utwórz studenta o podanym imieniu i ocenie
    
    // TODO: Utwórz kopię studenta
    
    // TODO: Wypisz informacje o oryginalnym studencie
    // Format: "Original: {name}, Grade: {grade}"
    
    // TODO: Wypisz informacje o kopii studenta
    // Format: "Clone: {name}, Grade: {grade}"
    
    // TODO: Zwolnij pamięć zajmowaną przez obu studentów
    
    // Wypisz potwierdzenie
    printf("Both freed\n");
    
    return 0;
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C online