Menu
Coddy logo textTech

Tiefe Kopie

Teil des Abschnitts Objektorientierte Programmierung der C-Journey von Coddy. Lektion 15 von 61.

Wenn du eine Struktur einer anderen in C zuweist, erhältst du eine flache Kopie: Alle Felder werden Byte für Byte kopiert. Das funktioniert bei einfachen Werten wie Ganzzahlen problemlos, führt aber bei Zeigern zu einem Problem: Beide Strukturen zeigen letztendlich auf denselben Speicher.

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

Person alice = {"Alice", 30};
Person copy = alice;  // Flache Kopie!
// Sowohl alice.name als auch copy.name zeigen auf denselben String

Wenn du eine freigibst, wird die andere ungültig. Wenn du die Zeichenkette über eine von beiden änderst, sehen beide die Änderung. Das ist nur selten das, was du möchtest.

Eine tiefe Kopie reserviert neuen Speicher für Zeigermitglieder und kopiert die tatsächlichen Daten:

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

Jetzt besitzt jedes Objekt seine eigene Zeichenkette. Du kannst eine davon ändern oder freigeben, ohne die andere zu beeinflussen. Das Muster ist unkompliziert: Weise für jedes Zeigermitglied neuen Speicher zu und kopiere den Inhalt, nicht nur die Adresse.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Student-Modul, das das Muster der tiefen Kopie demonstriert. Du erstellst eine Klonfunktion, die eine vollständig unabhängige Kopie eines Studentenobjekts erzeugt: eines Objekts, bei dem das Ändern oder Freigeben des Originals keine Auswirkungen auf den Klon hat.

Du erstellst drei Dateien:

  • student.h: Deklariere eine Student-Struktur mit zwei Mitgliedern: char *name (eine dynamisch reservierte Zeichenkette) und int grade. Deklariere drei Funktionen:
    • create_student: Konstruktor, der einen Namen und eine Note übernimmt und einen Zeiger auf einen neuen Student zurückgibt
    • clone_student: übernimmt einen const Student * und gibt einen Zeiger auf eine neue, unabhängige Kopie zurück
    • free_student: Destruktor, der den gesamten reservierten Speicher ordnungsgemäß freigibt
    Verwende Include-Guards mit dem Symbol STUDENT_H.
  • student.c: Implementiere alle drei Funktionen. Deine Funktion clone_student ist der entscheidende Teil. Sie muss neuen Speicher sowohl für die Struktur als auch für die Namenszeichenkette reservieren und anschließend die tatsächlichen Zeichenkettendaten kopieren (nicht nur die Zeigeradresse). Dadurch wird sichergestellt, dass der Klon vollständig eigenen Speicher besitzt, der vom Original getrennt ist.
  • main.c: Erstelle einen Studenten, klone ihn, zeige die Informationen beider Studenten an und räume anschließend beide Objekte ordnungsgemäß auf.

Du erhältst zwei Eingaben: den Studentennamen (eine Zeichenkette) und die Note (eine Ganzzahl).

Erstelle in deiner Hauptdatei einen Studenten mit den bereitgestellten Werten und erstelle anschließend einen Klon dieses Studenten. Gib die Informationen des Originals und des Klons aus, um zu überprüfen, dass sie dieselben Daten enthalten. Gib schließlich beide Studenten frei und gib eine Bestätigung aus.

Gib die Ausgabe in diesem Format aus:

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

Bei den Eingaben Alice und 95 würde die Ausgabe beispielsweise folgendermaßen aussehen:

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

Das Muster der tiefen Kopie stellt sicher, dass jedes Objekt wirklich unabhängig ist: Der Klon besitzt seine eigene reservierte Zeichenkette und keinen gemeinsam genutzten Zeiger auf den Speicher des Originals.

Probier es selbst

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

int main() {
    char name[100];
    int grade;
    
    // Eingabe lesen
    scanf("%s", name);
    scanf("%d", &grade);
    
    // TODO: Erstelle einen Studenten mit dem angegebenen Namen und der Note
    
    // TODO: Erstelle einen Klon des Studenten
    
    // TODO: Print the original student's information
    // Format: "Original: {name}, Grade: {grade}"
    
    // TODO: Gib die Informationen des Klons aus
    // Format: "Clone: {name}, Grade: {grade}"
    
    // TODO: Gib beide Studenten frei
    
    // Bestätigung ausgeben
    printf("Both freed\n");
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C-Compiler