Copie profonde
Fait partie de la section Programmation Orientée Objet du Journey C de Coddy. Leçon 15 sur 61.
Lorsque vous affectez une structure à une autre en C, vous obtenez une copie superficielle : tous les champs sont copiés octet par octet. Cela fonctionne parfaitement pour des valeurs simples comme les entiers, mais crée un problème avec les pointeurs : les deux structures finissent par pointer vers la même zone mémoire.
typedef struct {
char *name;
int age;
} Person;
Person alice = {"Alice", 30};
Person copy = alice; // Copie superficielle !
// alice.name et copy.name pointent tous les deux vers la MÊME chaîne
Si tu en libères un, l’autre devient invalide. Si tu modifies la chaîne par l’intermédiaire de l’un, les deux voient la modification. C’est rarement ce que tu souhaites.
Une copie profonde alloue une nouvelle zone mémoire pour les membres pointeurs et copie les données réelles :
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;
}
Désormais, chaque objet possède sa propre chaîne. Vous pouvez en modifier ou en libérer une sans affecter l’autre. Le principe est simple : pour chaque membre pointeur, allouez une nouvelle zone mémoire et copiez le contenu, pas seulement l’adresse.
Défi
FacileConstruisons un module Student qui illustre le modèle de copie profonde. Vous allez créer une fonction de clonage qui produit une copie complètement indépendante d’un objet étudiant : modifier ou libérer l’original n’aura aucun effet sur le clone.
Vous allez créer trois fichiers :
student.h: déclarer une structureStudentavec deux membres :char *name(une chaîne allouée dynamiquement) etint grade. Déclarer trois fonctions :create_student: constructeur qui prend un nom et une note, et renvoie un pointeur vers un nouveau Studentclone_student: prend unconst Student *et renvoie un pointeur vers une nouvelle copie indépendantefree_student: destructeur qui libère correctement toute la mémoire allouée
STUDENT_H.student.c: implémenter les trois fonctions. Votre fonctionclone_studentest l’élément clé. Elle doit allouer une nouvelle zone mémoire pour la structure et pour la chaîne du nom, puis copier les données réelles de la chaîne (et pas seulement l’adresse du pointeur). Cela garantit que le clone possède sa propre mémoire, complètement séparée de celle de l’original.main.c: créer un étudiant, le cloner, afficher les informations des deux étudiants, puis nettoyer correctement les deux objets.
Vous recevrez deux entrées : le nom de l’étudiant (une chaîne) et la note (un entier).
Dans votre fichier principal, créer un étudiant avec les valeurs fournies, puis créer un clone de cet étudiant. Afficher les informations de l’original et du clone pour vérifier qu’ils contiennent les mêmes données. Enfin, libérer les deux étudiants et afficher une confirmation.
Afficher la sortie dans ce format :
Original: {name}, Grade: {grade}
Clone: {name}, Grade: {grade}
Both freedPar exemple, avec les entrées Alice et 95, la sortie serait :
Original: Alice, Grade: 95
Clone: Alice, Grade: 95
Both freedLe modèle de copie profonde garantit que chaque objet est véritablement indépendant : le clone possède sa propre chaîne allouée, et non un pointeur partagé vers la mémoire de l’original.
Essayez vous-même
#include <stdio.h>
#include <stdlib.h>
#include "student.h"
int main() {
char name[100];
int grade;
// Lire l'entrée
scanf("%s", name);
scanf("%d", &grade);
// TODO: Créer un étudiant avec le nom et la note fournis
// TODO: Créer un clone de l'étudiant
// TODO: Print the original student's information
// Format : "Original: {name}, Grade: {grade}"
// TODO: Afficher les informations du clone
// Format : "Clone: {name}, Grade: {grade}"
// TODO: Libérer les deux étudiants
// Afficher la confirmation
printf("Both freed\n");
return 0;
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Bases de la programmation modulaire
Fichiers d'en-têteGardes d'inclusionFichiers sourcesFonctions statiquesRécapitulatif : Calculatrice modulaire4Encapsulation
Concept des pointeurs opaquesDéfinir des structures opaquesGetters et settersValidation dans les settersRécapitulatif : La boîte secrète2Objets et méthodes
Structs comme objetsLe pointeur 'Self'Rigueur du mot-clé constPointeur vs ValeurMéthodes utilitairesRécapitulatif : Point Manager5Projet : Compte bancaire simple
Configuration du projetImplémentation du compte8Polymorphisme
Pointeurs de fonctions dans les structuresSimulation de méthodesLe concept d'interfaceImplémentation d'interfacesItération polymorphiqueRécapitulatif : Greeter11Patrons de conception en C
Patron SingletonPatron FabriquePatron ItérateurRécapitulatif : Logger Factory3Cycle de vie des objets
Pattern de constructeurPattern de destructeurInitialisation sur la pileCopie profondeRécapitulatif : String Wrapper6Héritage par composition
Imbrication de structLa règle du premier membreAccès aux membres parentsUpcastingRécapitulatif : Hiérarchie des formes9Projet : Dessinateur de formes
Aperçu du projetImplémentation du cercleImplémentation du rectangleUtilisation polymorpheConteneur de formesEntraînez-vous par vous-même : Compilateur C en ligne