뚜둔뚜둔✩

판다의 개발일지

C · C++

[C++] 생성자와 초기화 리스트 (Initializer List)

2022. 5. 26. 01:06

    C++에서 생성자는 어떤 구조체 또는 클래스 객체의 생성 시 자동으로 호출되는 함수이다. 따라서 생성자에서는 흔히 초기화에 필요한 동작을 수행하게 되는데, 이때 멤버 변수를 초기화하는 데에는 2가지 방법이 있다.

    class Point
    {
    public:
    	Point(int x_val, int y_val);
    private:
    	int x;
        int y;
    };​

    (1) 생성자 함수 블록 내에서 멤버 변수 초기화 (대입)

    Point::Point(int x_val, int y_val)
    {
    	x = x_val;
        y = y_val;
    }

    (2) 초기화 리스트로 초기화 (초기화)

    Point::Point(int x_val, int y_val)
    	: x(x_val), y(y_val) { }

    초기화 리스트는 객체의 생성 후 값을 대입하는 것이 아닌, 객체의 생성과 동시에 값을 지정할 수 있게 한다. 이렇게 초기화 리스트를 사용하는 것은 direct initialization 또는 uniform initialization으로 초기화하는 것과 거의 동일하다.


    direct initialization와 uniform initialization

     

    [C++] 초기화 (Initialization)

    대입은 = 대입 연산자를 사용하여 어떤 변수에 값을 지정하는 것이다. 이를 "copy assignment"라고도 하는데, 그..

    pandas-are-bears.tistory.com


     

    초기화 리스트 사용하기

    초기화 리스트는 다음의 규칙을 따라야 한다.

     

    1) 초기화 리스트는 생성자 파라미터 이후 삽입된다.

    2) 초기화 리스트는 콜론(:)으로 시작하고, 초기화할 멤버 변수를 쉼표(,)로 구분하여 나열한다.

    3) 초기화 리스트는 세미콜론(;)으로 끝나지 않는다.

     

    상수(const)의 초기화

    초기화 리스트를 사용하면 클래스에 포함된 상수(const) 멤버도 초기화 할 수 있다.

    #include <iostream>
    
    class Object
    {
    public:
    	Object(int val) : c{ val } { }
    	void Print(void) { std::cout << "c is : "<< c << std::endl; }
    private:
    	const int c;
    };
    
    int main(void)
    {
    	Object var{ 12345 };
    
    	var.Print();
    
    	return 0;
    }
    c is : 12345

    대입으로 상수(const) 멤버에 값을 지정하는 것은 불가능하다.

    class Object
    {
    public:
    	Object(int val) { c = val; }
    private:
    	const int c;
    };
    main.cpp:4:2: error: constructor for 'Object' must explicitly initialize the const member 'c'
            Object(int val) { c = val; }
            ^
    main.cpp:6:12: note: declared here
            const int c;
                      ^
    main.cpp:4:22: error: cannot assign to non-static data member 'c' with const-qualified type 'const int'
            Object(int val) { c = val; }
                              ~ ^
    main.cpp:6:12: note: non-static data member 'c' declared const here
            const int c;
            ~~~~~~~~~~^
    2 errors generated.

     

    초기화 순서

    클래스 또는 구조체의 멤버가 초기화 되는 순서는 초기화 리스트에 나열된 순서와 관계 없다. 초기화의 순서는 클래스/구조체 내 멤버가 선언된 순서에 따라 초기화된다.

    그렇기 때문에 초기화 리스트로 초기화를 수행할 때, 한 멤버의 초기화가 다른 멤버의 초기화 순서에 영향을 받지 않도록 해야 한다. 또한, 일반적으로는 최대한 멤버가 선언된 순서에 따라 초기화 리스트를 구성하는 것을 권장한다.

    class Object
    {
    public:
    	Object(int val) : y{ val }, x{ y } { }
    private:
    	int x;
    	int y;
    };
    main.cpp:4:33: warning: field 'y' is uninitialized when used here [-Wuninitialized]
            Object(int val) : y{ val }, x{ y } { }
                                           ^
    1 warning generated.

     

     

    References

    https://www.learncpp.com/cpp-tutorial/constructor-member-initializer-lists/