Menu
Coddy logo textTech

복사 생성자

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

copy constructor는 기존 객체의 복사본으로 새 객체를 생성합니다. 동일한 유형의 다른 객체로 객체를 초기화하거나, 객체를 값으로 전달하거나, 객체를 값으로 반환할 때 호출됩니다.

copy constructor는 동일한 class의 객체에 대한 const 참조를 받습니다:

class Player {
    std::string name;
    int health;
public:
    Player(std::string n, int h) : name(n), health(h) {}
    
    // 복사 생성자
    Player(const Player& other) {
        name = other.name;
        health = other.health;
    }
};

Player original("Hero", 100);
Player copy = original;    // 복사 생성자가 호출됨
Player another(original);  // 역시 복사 생성자를 호출함

copy constructor를 정의하지 않으면 컴파일러가 각 member의 값을 직접 복사하는 얕은 복사를 수행하는 것을 자동으로 생성합니다. 단순한 유형에서는 잘 작동하지만, 클래스가 동적 메모리를 관리할 때 문제가 발생합니다.

class Buffer {
    int* data;
    size_t size;
public:
    Buffer(size_t s) : size(s) {
        data = new int[size];
    }
    
    // 깊은 복사 생성자
    Buffer(const Buffer& other) : size(other.size) {
        data = new int[size];              // 새 메모리 할당
        for (size_t i = 0; i < size; i++)
            data[i] = other.data[i];       // 내용 복사
    }
    
    ~Buffer() { delete[] data; }
};

사용자 지정 복사 생성자가 없으면, both 객체는 동일한 메모리를 가리키게 됩니다. 하나가 destroyed되면 다른 객체에는 댕글링 포인터가 생깁니다. 깊은 copy는 새 메모리를 할당하고 실제 데이터를 복사하여 각 객체가 자체 리소스를 소유하도록 합니다.

challenge icon

챌린지

쉬움

클래스가 동적 메모리를 관리할 때 깊은 복사의 중요성을 보여 주는 메시지 기록 시스템을 만들어 보겠습니다. 동적으로 할당된 array에 메시지를 저장하는 MessageLog class를 만들고, 각 복사본이 자체적인 독립 메모리를 갖도록 적절한 복사 constructor를 Implement합니다.

코드를 구성하기 위해 두 개의 파일을 만듭니다.

  • MessageLog.h: 동적 메모리를 사용하여 메시지 모음을 관리하는 MessageLog class를 define합니다. class에는 다음이 있어야 합니다.
    • Private members: 메시지 저장을 위한 string array 포인터, 최대 메시지 수를 나타내는 capacity, 현재 메시지 수를 나타내는 count
    • capacity를 인수로 받아 heap에 array를 할당하고 count를 0으로 Initializes하는 매개변수화된 constructor
    • 새 메모리를 할당하고 원본 객체의 모든 메시지를 복사하는 깊은 복사를 수행하는 복사 constructor
    • 할당된 메모리를 해제하고 "MessageLog destroyed"를 출력하는 destructor
    • 공간이 있으면 메시지를 추가하는 addMessage(string msg) method
    • 현재 메시지 count를 반환하는 getCount() method
    • 지정된 index의 메시지를 반환하는 getMessage(int index) method
  • main.cpp: 복사 constructor가 독립적인 복사본을 Create한다는 것을 보여 줍니다. input에서 capacity 값과 두 개의 메시지를 읽은 다음:
    • input capacity를 사용하여 original이라는 MessageLog를 Create합니다.
    • 두 메시지를 모두 original에 Add합니다.
    • 복사 constructor를 사용하여 backup이라는 복사본을 Create합니다.
    • 세 번째 메시지 "New message"original에만 Add합니다.
    • "Original count: <count>"를 출력합니다.
    • "Backup count: <count>"를 출력합니다.
    • backup의 모든 메시지를 한 줄에 하나씩 출력합니다.

input 형식은 다음과 같습니다.

  • 첫 번째 line: capacity (정수)
  • 두 번째 line: 첫 번째 메시지 (string)
  • 세 번째 line: 두 번째 메시지 (string)

깊은 복사가 올바르게 Implement되었다면, backup에는 2개의 메시지가 있고 original에는 3개의 메시지가 있어야 합니다. 이는 두 객체가 독립적인 메모리를 가지고 있음을 증명합니다. 적절한 복사 constructor가 없으면 둘 다 동일한 array를 공유하게 되어 한쪽의 변경 사항이 다른 쪽에 영향을 줍니다!

#include "MessageLog.h"를 사용하여 header file을 main.cpp에 Include합니다.

직접 해보기

#include <iostream>
#include <string>
#include "MessageLog.h"
using namespace std;

int main() {
    // 입력 읽기
    int capacity;
    cin >> capacity;
    cin.ignore();
    
    string msg1, msg2;
    getline(cin, msg1);
    getline(cin, msg2);

    // TODO: 입력 용량으로 'original'이라는 MessageLog 생성

    // TODO: 두 메시지를 모두 original에 추가

    // TODO: 복사 생성자를 사용하여 'backup'이라는 복사본 생성

    // TODO: "New message"를 original에만 추가

    // TODO: Print "Original count: <count>"

    // TODO: "Backup count: <count>" 출력

    // TODO: backup의 모든 메시지를 한 줄에 하나씩 출력

    return 0;
}
quiz icon실력 점검

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

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

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