C_C++

C++, 복사생성자 Copy Constructor

고니자니 2024. 11. 17. 08:25
반응형

C++에서 **복사 생성자(Copy Constructor)**는 객체가 같은 클래스의 다른 객체로부터 복사되어 초기화될 때 호출됩니다. 주로 다음 상황에서 호출됩니다:

  1. 객체가 복사로 초기화될 때.
  2. 객체가 함수에 값으로 전달될 때.
  3. 함수에서 객체를 값으로 반환할 때.

복사 생성자의 기본 형태

ClassName(const ClassName& other);

const는 복사 생성자가 원본 객체를 수정하지 않도록 보장합니다.

 

예제

아래는 복사 생성자를 정의하고 사용하는 간단한 예제입니다.

#include <iostream>
#include <cstring>

class MyClass {
private:
    char* name; // 동적으로 관리되는 문자열

public:
    // 기본 생성자
    MyClass(const char* inputName) {
        name = new char[strlen(inputName) + 1];
        strcpy(name, inputName);
        std::cout << "Constructor called for: " << name << std::endl;
    }

    // 복사 생성자
    MyClass(const MyClass& other) {
        name = new char[strlen(other.name) + 1]; // 깊은 복사
        strcpy(name, other.name);
        std::cout << "Copy Constructor called for: " << name << std::endl;
    }

    // 소멸자
    ~MyClass() {
        delete[] name;
        std::cout << "Destructor called for: " << name << std::endl;
    }

    // 이름 출력 함수
    void printName() const {
        std::cout << "Name: " << name << std::endl;
    }
};

int main() {
    MyClass obj1("Original");  // 기본 생성자 호출
    MyClass obj2 = obj1;       // 복사 생성자 호출 (obj2는 obj1의 복사본)
    obj1.printName();          // obj1 출력
    obj2.printName();          // obj2 출력

    return 0; // 소멸자 호출
}

Constructor called for: Original
Copy Constructor called for: Original
Name: Original

Name: Original
Destructor called for: Original
Destructor called for: Original

 

복사 생성자 없이 사용하는 경우

만약 복사 생성자를 정의하지 않으면 컴파일러는 기본 복사 생성자를 제공합니다. 그러나 기본 복사 생성자는 **얕은 복사(Shallow Copy)**를 수행합니다. 얕은 복사는 포인터의 값을 복사하므로, 두 객체가 같은 메모리 주소를 참조하게 됩니다. 이로 인해 소멸자에서 동일한 메모리를 두 번 해제하려고 할 수 있습니다(이중 해제 문제).

 

깊은 복사와 얕은 복사

  • 얕은 복사(Shallow Copy): 포인터나 동적 메모리 같은 복합 객체의 주소만 복사합니다.
  • 깊은 복사(Deep Copy): 실제 데이터를 새롭게 복사하여 각 객체가 독립적인 메모리를 가집니다.

복사 생성자의 필요성

  • 동적 메모리를 사용하는 클래스는 반드시 복사 생성자를 정의하여 깊은 복사를 구현해야 합니다.
  • 현대 C++에서는 복사 생성자 대신 Move Constructor와 스마트 포인터를 사용하는 것이 권장됩니다.
반응형