[Modern C++] 16.1. 유니폼 초기화(Uniform Initialization)

윤정민·2023년 8월 13일
0

C++

목록 보기
41/46

1. 서론

C++에서 ()은 함수의 인자들을 정의하는데도 사용되고 일반적인 객체의 생성자를 호출할 때도 사용되기 때문에 컴파일러는 함수의 정의처럼 보이는 것들은 모두 함수의 정의로 해석한다. 따라서 아래의 코드처럼 생성자를 호출하였지만 함수의 정으로 해석되는 문제가 발생한다. 이를 해결하기 위해 균일한 초기화라는 것을 사용한다.

#include <iostream>

class A {
 public:
  A() { std::cout << "A 의 생성자 호출!" << std::endl; }
};

int main() {
  A a();  // ?
}

2. 균일한 최기화(Uniform Initialization)

  • 해당 문법을 사용하기 위해서는 생성자를 호출할 때 ()대신 {}를 사용

  • {}를 사용하면 암시적 타입 변환이 불가능

  • 예시 코드

    #include <iostream>
    
    class A {
     public:
      A() { std::cout << "A 의 생성자 호출!" << std::endl; }
    };
    
    int main() {
      A a{};  // 균일한 초기화!
    }
  • 코드 결과: A 의 생성자 호출!

3. 초기화자 리스트(Initializer list)

  • {}를 이용해 생성자를 호출할 때, 클래스의 생성자들 중에서 initializer_list를 인자로 받는 생성자가 있다면 전달됨

    • () 를 사용해서 생성자를 호출한다면 intializer_list 가 생성되지 않음
  • 예시 코드

    #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}; }
  • 주의점

    • {}를 사용해 객체를 생성할 경우 생성자 오버로딩 시에 해당 함수가 최우선으로 고려됨

4. initialize_list와 auto

  • {}를 이용해 생성할 때 타입으로 auto를 지정한다면 initializer_list객체가 생성됨
    auto a = {1};     // 첫 번째 형태이므로 std::initializer_list<int>
    auto b{1};        // 두 번째 형태 이므로 그냥 int
    auto c = {1, 2};  // 첫 번째 형태이므로 std::initializer_list<int>
    auto d{1, 2};  // 두 번째 형태 인데 인자가 2 개 이상이므로 컴파일 오류
  • 문자열을 {}로 초기화 한다면 initializer_list<std::string>이 아닌 initializer_list<const char*>이 됨
    auto list = {"a", "b", "cc"};
    • 이는 리터럴 연산자를 통해 해결가능
    using namespace std::literals;  // 문자열 리터럴 연산자를 사용하기 위해
                                    // 추가해줘야함.
    auto list = {"a"s, "b"s, "c"s};
profile
그냥 하자

0개의 댓글