Rule of Three

Yerin·2024년 11월 12일

클래스가 다음 중 하나를 정의하는 경우
(1) 소멸자 (2) 복사 생성자 (3) 복사 대입 연산자 세 가지를 함께 정의해야 한다는 규칙이다.

이 규칙을 통해 리소스 관리가 더 안전하고 예측 가능해지며, 메모리 누수와 같은 문제를 방지할 수 있다. 물론 일관성 유지는 덤이다.

이 세가지에 대해 잘 모르는 분들을 위해 설명을 덧붙여본다.


소멸자 (Destructor)

객체가 삭제될 때 자동으로 호출된다.
소멸자는 주로 객체가 사용하던 동적 메모리나 파일 핸들 같은 자원을 정리하고 반환하는 역할을 한다.
→ 프로그램이 메모리 누수 없이 효율적으로 자원을 관리할 수 있다.

현재 String 클래스를 작성해보는 실습을 만들고 있어서 예제로 가져와봤다. 아래 예시와 같이 보통 동적 메모리를 해제하는 로직을 추가해준다.

class String {
private:
    char* str;

public:
    String (int size) {
	      // 동적 메모리 할당
        str = new char[size];
    }

    ~String () {
        // 동적 메모리 해제
        delete[] str;  
    }
};

복사 생성자 (Copy Constructor)

객체를 복사하여 새로운 객체를 만들 때 호출되는 생성자이다.
객체가 다른 객체를 통해 초기화될 때(복사할 때) 자원이 안전하고 올바르게 복사되도록 도와준다.
기본적으로 C++는 복사 생성자를 자동으로 만들어주지만, 동적 메모리나 특정 자원을 사용하는 경우, 복사 생성자를 직접 정의해 줘야한다.

내부에서는 다음과 같이 메모리 할당 후 데이터를 복사해주면된다. 이렇게 하면 단순히 포인터 값만 복사하는 것이아니므로 얕은 복사 문제를 일으키지 않는다.

class String {
private:
    char* str;

public:
    String (const Srting& origin) {
        str = new char[origin.length() + 1]; 
	      strcpy(str, origin.str);
    }
};

복사 대입 연산자 (Copy Assignment Operator)

이미 존재하는 객체에 다른 객체의 값을 복사할 때 호출되는 연산자이다.
아래 예시와 같이 기존 자원을 해제하고 값을 복사해주어야한다.

class String {
private:
    char* str;

public:
    String& operator=(const Srting& origin) {
        // 본인 복사 방지
	      if (this == &other) return *this
    
		    delete[] str;
		    
		    str = new char[origin.length() + 1];
		    strcpy(str, origin.str);
		    
		    return *this;
    }
};

특별하게 어려운 내용은 없으나, C++에서 클래스 생성자 관련하여 꼭 알아야할 점이라고 생각해서 포스팅한다.

The rule of three/five/zero

profile
𝙸 𝚐𝚘𝚝𝚝𝚊 𝚕𝚒𝚟𝚎 𝚖𝚢 𝚕𝚒𝚏𝚎 𝙽𝙾𝚆, 𝙽𝙾𝚃 𝚕𝚊𝚝𝚎𝚛 !

0개의 댓글