Menu
Coddy logo textTech

깊은 복사

Coddy C 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 61개 중 15번째.

C에서 한 구조체를 다른 구조체에 할당하면 얕은 복사가 이루어집니다. 모든 필드는 바이트 단위로 그대로 복사됩니다. 이는 정수와 같은 단순한 값에는 잘 작동하지만, 포인터에서는 문제가 발생합니다. 두 구조체가 결국 동일한 메모리를 가리키게 되기 때문입니다.

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

Person alice = {"Alice", 30};
Person copy = alice;  // 얕은 복사!
// alice.name과 copy.name 모두 동일한 문자열을 가리킵니다

하나를 free하면 다른 하나는 유효하지 않게 됩니다. 하나를 통해 문자열을 수정하면 둘 다 변경 사항을 확인하게 됩니다. 이는 거의 여러분이 원하는 방식이 아닙니다.

깊은 복사는 포인터 멤버를 위한 새 메모리를 할당하고 실제 데이터를 복사합니다:

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

이제 각 객체가 자신의 문자열을 소유합니다. 한 객체를 수정하거나 free해도 다른 객체에는 영향을 주지 않습니다. 패턴은 간단합니다. 각 포인터 멤버에 대해 새 메모리를 할당하고 주소만이 아니라 내용을 복사합니다.

challenge icon

챌린지

쉬움

Student 모듈을 만들어 깊은 복사 패턴을 살펴보겠습니다. 학생 객체의 완전히 독립적인 복사본을 생성하는 복제 function을 만들게 됩니다. 즉, 원본을 수정하거나 해제해도 복제본에는 아무런 영향이 없습니다.

세 개의 파일을 만들게 됩니다:

  • student.h: 두 멤버를 가진 Student 구조체를 Declare합니다: char *name(dynamically 할당된 문자열)과 int grade입니다. 세 function을 Declare합니다:
    • create_student: 이름과 성적을 받아 새로운 Student에 대한 포인터를 반환하는 constructor
    • clone_student: const Student *를 받아 새롭고 independent한 복사본에 대한 포인터를 반환
    • free_student: 할당된 모든 메모리를 올바르게 해제하는 destructor
    STUDENT_H 기호를 사용하여 include guard를 사용합니다.
  • student.c: 세 function을 모두 Implement합니다. clone_student function이 핵심입니다. 구조체와 name 문자열 모두에 대해 fresh 메모리를 Allocate한 다음, 실제 문자열 data를 복사해야 합니다(단순히 포인터 주소만 복사해서는 안 됩니다). 이렇게 하면 복제본이 원본과 완전히 분리된 자체 메모리를 소유하게 됩니다.
  • main.c: 학생을 Create하고, 복제한 다음, 두 학생의 information을 표시하고, 마지막으로 두 객체를 올바르게 정리합니다.

두 개의 입력을 받습니다: student name(문자열)과 grade(정수)입니다.

main 파일에서 제공된 값으로 학생을 Create한 다음, 해당 학생의 복제본을 Create합니다. 원본과 복제본의 information을 모두 출력하여 두 객체가 동일한 data를 포함하는지 확인합니다. 마지막으로 두 학생을 모두 해제하고 confirmation을 출력합니다.

다음 형식으로 출력을 출력합니다:

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

예를 들어 입력이 Alice95인 경우 출력은 다음과 같습니다:

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

deep copy 패턴은 각 객체가 진정으로 independent하다는 것을 보장합니다. 복제본은 원본의 메모리에 대한 공유 포인터가 아니라 자체적으로 Allocate된 문자열을 가집니다.

직접 해보기

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

int main() {
    char name[100];
    int grade;
    
    // 입력 읽기
    scanf("%s", name);
    scanf("%d", &grade);
    
    // TODO: 제공된 이름과 성적으로 학생 생성
    
    // TODO: 학생의 클론 생성
    
    // TODO: Print the original student's information
    // 형식: "Original: {name}, Grade: {grade}"
    
    // TODO: 클론의 정보 출력
    // 형식: "Clone: {name}, Grade: {grade}"
    
    // TODO: 두 학생 모두 해제
    
    // 확인 출력
    printf("Both freed\n");
    
    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 C 컴파일러