ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 항목17. 특수 멤버 함수들의 자동 작성 조건을 숙지하라.
    Effective Modern C++ 2022. 7. 29. 23:17

    특수 멤버 함수들은 C++이 기꺼이 작성하는 멤버 함수들을 가리킨다. 기본 생성자, 소멸자, 복사 생성자, 복사 배정 연사자가 있다. 기본 생성자는 클래스에 생성자가 하나도 선언되어 있지 않을 때 생성된다. 작성된 특수 멤버 함수들은 암묵적으로 public이자 inline이며, 가상 소멸자가 있는 기반 클래스를 상속하는 파생 클래스의 소멸자를 제외하고는 non-virtual이다.(반대 경우는 virtual) C++11에서는 이동 생성자와 이동 배정 연산자가 추가됐다.

    Widget(Widget&& rhs);               // 이동 생성자
    Widget& operator=(Widget&& rhs);    // 이동 배정 연산자

    복사 연산은 서로 독립적이다. 복사 생성자를 선언했지만 복사 배정 연산자는 선언하지 않았다면, 그러나 복사 배정 연산이 필요한 클라이언트 코드를 작성했다면, 컴파일러가 자동으로 복사 배정 연산자를 작성한다. 반대도 똑같다. 이동 연산은 독립적이지 않다. 어느 하나가 선언돼 있으면 다른 하나는 자동 생성되지 않는다.

    복사 연산을 하나라도 명시적으로 선언하면 이동 연산들이 자동으로 작성되지 않는다. 반대로 이동 연산들을 하나라도 명시적으로 선언하면 복사 연산들이 자동으로 작성되지 않는다.

    • 3의 법칙 : 만일 복사 생성자와 복사 배정 연산자, 소멸자 중 하나라도 선언했다면 나머지 둘도 선언해야 한다.
    • 사용자 선언 소멸자가 있는 클래스는 이동 연산들을 작성하지 않는다.

    사용자 정의 소멸자를 선언했지만 기본 복사 생성자와 기본 복사 배정을 사용하고 싶을 때

    class Widget {
    public:
        ...
        ~Widget();                                  // 사용자 정의 소멸자
        Widget(const Widget&) = default;            // 기본 복사 생성자
        Widget& operator=(const Widget&) = default; // 기본 복사 배정
    };

    소멸자를 virtual로 선언하지만 기본 구현이 적합한 경우도 있다. 그럴 때 =default를 선언하면 좋다. 그리고 소멸자를 직접 선언하면 이동 연산들의 자동 작성이 금지되니 이동 연산들을 =default로 선언하고, 이동 생성자를 직접 선언하면 복사 연산들의 자동 작성이 금지되니 복사 연산들을 =default로 선언하면 된다.

    class Base {
    public:
        virtual ~Base() = default;                // 가상 소멸자   
    
        Base(Base&&) = default;                   // 이동 지원
        Base& operator=(Base&&) = default;
    
        Base(const Base&) = default;              // 복사 지원
        Base& operator=(const Base&) = default; 
        ...
    };

    멤버 함수 템플릿이 존재해도 특수 멤버 함수는 자동 작성됨.

    class Widget {
        ...
        template<typename T>
        Widget(const T& rhs);
    
        template<typename T>
        Widget& operator=(const T& rhs);
    
        // 컴파일러는 여전히 Widget의 복사 연산들과 이동 연산들을 작성한다.
    };
Designed by Tistory.