개발자 면접 공부/C-C++

초기화자 리스트(intializer_list)

chogyujin 2024. 3. 8. 16:30
728x90

1. 개요

오늘은 초기화자 리스트(Initializer_list)에 대해서 공부하도록 하겠습니다.


2. 초기화자 리스트란?

초기화자 리스트란 중괄호를 사용해서 배열 및 벡터를 초기화할때 많이 사용하는 방식입니다.

int arr[] = {1, 2, 3, 4};

이러한 코드를 많이 보셨을거라 판단됩니다.

그렇다면 아래의 코드는 과연 가능할까요?

vector<int> v = {1, 2, 3, 4};

물론 가능합니다.
C++11부터 사용자에게도 이러한 문법을 사용할수 있도록 하게 하였습니다.

#include <iostream>

class A 
{
public:
    A(std::initializer_list<int> l)
    {
        for (auto itr = l.begin(); itr != l.end(); ++itr) 
        {
            std::cout << *itr << std::endl;
        }
    }
};

int main()
{ 
    A a = { 1, 2, 3, 4, 5 }; 
}

컴파일을 완료가 되었다면

이러한 결과값을 확인할수 있습니다.

초기화자 리스트는 우리가 {} 를 이용해서 생성자를 호출할 때, 클래스의 생성자들 중에 initialize_list를 인자로 받는 생성자가 있다면 전달됩니다.


2. 주의점

생성자들 중에서 initializer_list 를 받는 생성자가 있다면 한 가지 주의해야할 점이 있습니다.
만일{}를 이용해서 객체를 생성할 경우 생성자 오버로딩 시에 해당 함수가 최우선 으로 고려된다는 점입니다.

예를 들어서 vector 의 경우 아래의 같은 형태의 생성자가 존재합니다.

vector(size_type count);

이 생성자는 count 개수 만큼의 원소 자리를 미리 생성해놓습니다(size를 생성함)

vector v{10};

이러면 어떻게 될까요? 생성자를 호출하나요? 아닙니다. 그냥 원소 1개 짜리 initializer_list 라고 생각해서 10을 보관하고 있는 벡터를 생성하게 됩니다.

따라서, 이러한 불상사를 막기 위해서는 {}로 생성하기 보다는 ()를 이용해서

vector v(10);

과 같이 v 를 생성한다면 우리가 원하는 생성자를 호출할 수 있게 됩니다.

initializer_list 를 받는 생성자가 최우선적으로 고려된다는 말은, 컴파일러가 최선을 다해서 해당 생성자와 매칭시키려고 노력한다는 의미와 같고, 예를 들어서 아래와 같은 코드를 살펴보면

#include <iostream>

class A 
{
public:
    A(int x, double y) 
    {
        std::cout << "일반 생성자! " << std::endl;
    }

    A(std::initializer_list<int> lst) 
    {
        std::cout << "초기화자 사용 생성자! " << std::endl;
    }
};

int main() {
    A a(3, 1.5);  // Good
    A b{ 3, 1.5 };  // Bad!
}

오류가 생깁니다.

앞서 설명에는 {}는 데이터 손실이 있는 변환을 할 수 없다고 말했습니다. 그럼 string은 가능할까요?

https://chogyujin-study.tistory.com/118

 

유니폼 초기화

1. 개요 오늘은 C++의 유니폼 초기화에 대해서 공부해보겠습니다. 2. 개념 유니폼 초기화(균일한 초기화)라고 말을 합니다. 아래의 코드를 봅시다. #include class A { public: A() { std::cout

chogyujin-study.tistory.com

#include <initializer_list>
#include <iostream>
#include <string>

class A 
{
public:
    A(int x, double y) 
    {
        std::cout << "일반 생성자! " << std::endl; 
    }

    A(std::initializer_list<std::string> lst)
    {
        std::cout << "초기화자 사용 생성자! " << std::endl;
    }
};

int main() 
{
    A a(3, 1.5);        // 일반
    A b{ 3, 1.5 };        // 일반
    A c{ "abc", "def" };  // 초기화자
}

가능은 합니다 int 나 doulbe이 string으로 변환될 수 없기 때문에 initializer_list를 받는 생성자는 아예 고려 대상에서 제외됩니다.


3. Ref

https://modoocode.com/286

 

씹어먹는 C++ - <16 - 1. C++ 유니폼 초기화(Uniform Initialization)>

유니폼 초기화 ({} 를 이용한 생성자 호출) 를 통해서 인자 없는 생성자가 함수의 정의로 오해되는 일을 막을 수 있으며 initializer_list 를 만들어 전달할 수 있습니다. initializer_list 를 통해서 객체

modoocode.com

 

'개발자 면접 공부 > C-C++' 카테고리의 다른 글

NULL 포인터로 객체의 함수가 왜 호출되냐?  (0) 2024.03.26
VTable 위치 파악  (0) 2024.03.25
유니폼 초기화  (0) 2024.03.06
C++ vs C#  (1) 2024.02.18
Move Semantics  (0) 2023.10.29