복사 생성자
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는 새 메모리를 할당하고 실제 데이터를 복사하여 각 객체가 자체 리소스를 소유하도록 합니다.
챌린지
쉬움클래스가 동적 메모리를 관리할 때 깊은 복사의 중요성을 보여 주는 메시지 기록 시스템을 만들어 보겠습니다. 동적으로 할당된 array에 메시지를 저장하는 MessageLog class를 만들고, 각 복사본이 자체적인 독립 메모리를 갖도록 적절한 복사 constructor를 Implement합니다.
코드를 구성하기 위해 두 개의 파일을 만듭니다.
MessageLog.h: 동적 메모리를 사용하여 메시지 모음을 관리하는MessageLogclass를 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
- Private members: 메시지 저장을 위한 string array 포인터, 최대 메시지 수를 나타내는
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 capacity를 사용하여
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;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 C++ 컴파일러