본문 바로가기
C++

객체 초기화 방법

by Oz Driver 2026. 1. 9.

1. 생성자 본문 대입 (기존 방식)

이 방식은 생성자 본문 { } 안에서 = 연산자를 사용하여 이미 생성된 멤버 변수에 값을 대입하는 방식입니다.

class Player 
{
public:
    std::string name; // 복잡한 객체
    int level;

    // (1) 생성자 본문 대입 방식
    Player(std::string n, int l) 
    {
        // name 멤버는 여기서 'n' 값을 할당받기 전에,
        // 이미 기본값("")으로 초기화된 상태입니다.
        name = n;    // 불필요한 대입 복사 발생
        level = l;
    } 
};

 

이 방식은 초기화 후, 대입이라는 2 단계를 거치게 됩니다. 

즉, name 멤버 변수가 생성자 본문이 실행되기 전에 먼저 std::string() (빈 문자열)으로 자동 초기화됩니다.

그 후, name = n; 코드를 통해 n의 값이 이미 초기화된 name에 덮어씌워지며 불필요한 자원 이동/복사가 추가로 발생합니다.

const 멤버 변수나 참조(&) 멤버는 생성 후 값을 바꿀 수 없으므로, 이 방식으로 초기화 자체가 불가능합니다.

 

2. 멤버 초기화 리스트 (권장 방식)

이 방식은 생성자 매개변수 뒤에 콜론 (:) 을 사용하여 멤버를 직접 초기화하는 방식입니다.

class Player 
{
public:
    std::string name;
    int level;
    
    // (2) 멤버 초기화 리스트 방식
    // 콜론 뒤에 멤버와 값을 괄호로 묶어 나열 (쉼표 구분)
    Player(std::string n, int l) : name(n), level(l) 
    {
        // 생성자 본문({})이 실행될 때, 
        // name과 level은 이미 초기화가 완료된 상태입니다.
    }
}


작성 방법은 생성자 뒤에 콜론 (:) 을 찍고, 초기화가 필요한 멤버(값), 멤버2(값2) 형태로 쉼표로 구분하여 나열합니다.

이 방식의 장점은 멤버 변수가 기본값 초기화 단계를 건너뛰고, 전달된 값(n, l)으로 처음부터 바로 초기화되기 때문에 보다 효율적입니다.

또한  const 멤버나 참조(&) 멤버를 포함한 모든 종류의 멤버를 올바르게 초기화할 수 있는 방식입니다. 

Modern C++ : 중괄호 {}를 통한 안전성 확보

현대에 와서는 모든 초기화를 중괄호 { } 로 통일했습니다.

따라서 name, level 뒤 인자도 { } 로 감싸 주었습니다.

물론 기존 방식대로 괄호 ( ) 를 써도 무방합니다만, { } 로 썼을 때의 잇점은 인자로 넣은 타입과 선언된 타입이 다를 경우, 컴파일 에러를 발생시켜 축소 변환(Narrowing Conversion)을 원천적으로 차단합니다. 예를 들어 int 변수에 float 값을 넣으면 ( ) 방식은 안에서 int로 자동 변환되어 잘못된 값을 인지 못하게 될 수 있는 위험에 대비하기 위함입니다.

class Player 
{
public:
    std::string name;
    int level;
    
    // (2) 멤버 초기화 리스트 방식
    // 콜론 뒤에 멤버와 값을 괄호로 묶어 나열 (쉼표 구분)
    Player(std::string n, int l) : name{n}, level{l} 
    {
        // 생성자 본문({})이 실행될 때, 
        // name과 level은 이미 초기화가 완료된 상태입니다.
    }
}

// 기존 괄호 방식 (level(3.14f)): 3.14f가 조용히 3으로 잘려 들어감 (버그 유발 가능)
Player player ( "Hellow", 3.14f );

// - 중괄호 방식 (level{3.14f}): 컴파일 에러 발생! (개발자에게 문제 통보)
Player player { "Hellow", 3.14f };