티스토리 뷰

728x90

 

C++이 자동으로 생성하고 호출하는 함수들에 주의하자


class Empty { };

class Empty 
{
public:
    Empty() { /* ... */ }                                   // 기본 생성자
    Empty(const Empty& rhs) { /* ... */ }                   // 복사 생성자
    ~Empty() { /* ... */ }                                  // 소멸자
    Empty& operator=(const Empty& rhs) { /* ... */ }        // 복사 대입 연산자
};

C++에서는 프로그래머가 명시적으로 선언하지 않아도 컴파일러가 자동으로 생성해주는 멤버 함수들이 있습니다. 이러한 함수들에는 기본 생성자, 복사 생성자, 복사 대입 연산자, 소멸자가 포함됩니다. 컴파일러가 생성하는 이 함수들은 모두 public 멤버이며 inline 함수입니다.

자동으로 생성된 복사 생성자는 객체의 각 멤버를 해당 멤버의 복사 생성자를 이용하여 초기화합니다.


예제 1


template<typename T>
class NamedObject 
{
public:
    // 사용자가 직접 정의한 생성자가 있으면 기본 생성자는 자동으로 생성되지 않습니다.
    NamedObject(const char* name, const T& value);          
    NamedObject(const std::string& name, const T& value);  
    // 생성자가 하나도 없을 때만 기본 생성자가 자동으로 생성됩니다.
private:
    std::string nameValue;
    T objectValue;
};

NamedObject<int> no1("Smallest Prime Number", 2);
NamedObject<int> no2(no1); // 여기서 자동 생성된 복사 생성자를 호출합니다.
// NamedObject의 각 멤버인 nameValue와 objectValue의 복사 생성자가 호출됩니다.

위 코드에서 no2를 생성할 때 자동 생성된 복사 생성자가 호출됩니다. 이때 nameValuestd::string 타입이므로 해당 복사 생성자가 호출되고, objectValue는 기본 타입인 int이므로 값이 그대로 복사됩니다.

자동 생성된 복사 대입 연산자도 이와 비슷한 원리로 작동합니다. 하지만 모든 경우에 자동으로 생성되지는 않습니다. 예를 들어, 클래스 멤버 중에 참조자const 멤버가 있으면 컴파일러는 복사 대입 연산자를 자동으로 생성할 수 없으며, 이 경우 컴파일 에러가 발생합니다. 이는 참조자는 다른 대상을 참조하도록 변경할 수 없고, const 멤버는 값을 변경할 수 없기 때문입니다.

또한, 복사 대입 연산자가 private로 선언된 클래스를 상속받은 파생 클래스에서는 복사 대입 연산자가 자동으로 생성되지 않습니다.


결론

컴파일러는 상황에 따라 클래스에 대해 기본 생성자, 복사 생성자, 복사 대입 연산자, 소멸자를 암시적으로 생성할 수 있습니다. 그러나 객체 내부에 새로운 멤버가 추가되면, 생성자, 대입 연산자, 소멸자를 새로 정의해주는 것이 좋습니다.

특히 클래스 내에 참조자const 멤버 변수가 있는 경우, 컴파일러는 자동으로 복사 생성자나 복사 대입 연산자를 생성할 수 없으므로, 프로그래머가 직접 이들 함수를 정의해야 합니다. 이를 통해 객체의 올바른 복사 및 대입 동작을 보장할 수 있습니다.

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함
250x250