C++ Constructor와 관련된 개념들을 몇 가지 정리하려고합니다.

위임 생성자

C++11부터 도입된 위임 생성자는 한 생성자가 같은 클래스의 다른 생성자에게 초기화 작업을 위임할 수 있는 기능입니다.

  class Point {
private:
    int x, y;
public:
    Point(int x, int y) : x(x), y(y) {} // 타겟 생성자
    Point() : Point(0, 0) {}            // 위임 생성자
};
  

위임 생성자를 사용하면 코드 중복을 줄이고 초기화 로직을 한 곳에 모을 수 있습니다.

Default/Delete constructor

C++11에서는 default와 delete 키워드를 통해 특수 멤버 함수의 자동 생성을 제어할 수 있습니다.

  public:
    // 컴파일러가 기본 생성자 자동 생성
    Example() = default;
    
    // 복사 생성자 삭제 (복사 방지)
    Example(const Example&) = delete;
;
  
  • = default: 컴파일러에게 해당 특수 멤버 함수를 기본 구현으로 생성하도록 지시
  • = delete: 해당 특수 멤버 함수의 사용을 금지

explicit 생성자

explicit 키워드는 생성자에서 의도하지 않은 암시적 타입 변환을 방지합니다.

  class FileWrapper {
public:
    // 문자열에서 FileWrapper로의 암시적 변환 방지
    explicit FileWrapper(const char* filename);
};

// 사용 예시
FileWrapper f1("data.txt");     // 직접 초기화: 허용됨
// FileWrapper f2 = "data.txt"; // 복사 초기화: 컴파일 오류

void processFile(FileWrapper fw);
// processFile("data.txt");     // 컴파일 오류: 암시적 변환 불가
processFile(FileWrapper("data.txt")); // 명시적 변환: 허용됨
  

표준 라이브러리에서도 많이 사용됩니다:

  vector<int> v1(10);       // 가능: 10개 요소 벡터
// vector<int> v2 = 10;   // 오류: explicit 생성자
shared_ptr<int> p1(new int); // 가능
// shared_ptr<int> p2 = new int; // 오류: explicit 생성자
  

복사 생성자

복사 생성자는 같은 클래스의 다른 객체로부터 새 객체를 초기화할 때 호출됩니다.

  class MyClass {
public:
    MyClass(const MyClass& other); // 복사 생성자
};
  

복사 생성자가 호출되는 상황:

  1. 객체를 같은 타입의 다른 객체로 초기화할 때

      MyClass obj1;
    MyClass obj2(obj1);   // 직접 초기화
    MyClass obj3 = obj1;  // 복사 초기화
    MyClass obj4{obj1};   // 유니폼 초기화 (C++11)
      
  2. 함수에 객체를 값으로 전달할 때 (call by value)

      void func(MyClass obj); // 인자로 전달 시 복사 생성
      
  3. 함수가 객체를 값으로 반환할 때

      MyClass getValue() { 
        MyClass temp;
        return temp; // 반환 시 복사 생성 (최적화될 수 있음)
    }
      

복사 금지

  class NoCopyClass {
public:
    NoCopyClass(const NoCopyClass&) = delete;
    NoCopyClass& operator=(const NoCopyClass&) = delete;
};
  

static member data

static 멤버 데이터는 클래스의 모든 인스턴스가 공유하는 데이터입니다.

  class Counter {
public:
    // C++11 이전: 클래스 내부에서는 선언만 가능
    static int count;
    
    // 정수형 상수는 클래스 내에서 초기화 가능
    static const int MAX_COUNT = 100;
    
    // C++11: constexpr 정적 멤버 (정수 외에도 가능)
    static constexpr double VERSION = 1.2;
    
    // C++17: inline 정적 멤버 (별도 정의 필요 없음)
    inline static int activeInstances = 0;
};

// C++17 이전에는 클래스 외부에서 정의 필요
int Counter::count = 0;
  

const member function

const 멤버 함수는 객체의 상태를 변경하지 않는 함수를 명시합니다.

  class DataHolder {
    int data;
    mutable int accessCount;  // const 함수에서도 수정 가능
    
public:
    // const 멤버 함수: 객체 상태를 변경하지 않음
    int getData() const {
        accessCount++;  // mutable 멤버는 수정 가능
        return data;
    }
    
    // const 반환: 반환된 포인터로 데이터 수정 방지
    const int* getDataPtr() const {
        return &data;
    }
};
  

const 멤버 함수의 특징:

  1. 상수 객체는 상수 멤버 함수만 호출 가능
  2. 함수 내에서 멤버 변수 수정 불가 (mutable 제외)
  3. 함수가 const 참조로 객체를 받을 때도 중요