상세 컨텐츠

본문 제목

[C++11] Converting constructors (Braced list syntax)

C++/Modern C++(11, 14, 17, 20)

by deulee 2023. 8. 24. 16:27

본문

이제 변환 생성자는 '중괄호로 묶여진 값들도 생성자의 인자로 받아들인다'.

 

#include <iostream>

class A {
public:
	A(int) {}
	A(int, int) {}
	A(int, int, int) {}
};

int main(void)
{
	A a {0, 0}; // calls A::A(int, int);
	A b{0, 0}; // calls A::A(int, int);
	A c = {0, 0}; // calls A::A(int, int);
	A d {0, 0, 0}; // calls A::A(int, int, int);
}

하지만 여기에는 특별한 규칙이 있는데 '축소 변환(narrowing)' 같은 상황을 방지한다.

A e(1.1); // calls A::A(int);
A f {1.1}; // error

그리고 다음과 같은 상황이 가능하다.

A g(); // A를 리턴하는 함수 g 선언

A h{}; // 기본 생성자 호출

`A g()`를 사용했을때 우리가 기대했던 것은 `A`의 기본 생성자를 호출하는 것이였을 테지만, 컴파일러 입장에서 보면 `A`를 리턴하는 함수 `g`의 선언으로밖에 보이지 않는다.

 

하지만 `A h{}`를 사용하게 되면 컴파일러 입장에서 `A`의 기본 생성자를 호출하려는 의도를 파악할 수 있다.

 

그리고 만약 생성자가 `std::initializer_list`를 인수로 받아들인다면 어떤 상황에서든 `{}` 초기화는 해당 생성자를 호출할 것이다.

 

이는 벡터와 같이 인수를 무한으로 받아들이고자 할 때 유용하게 사용된다.

struct A {
  A(int) {}
  A(int, int) {}
  A(int, int, int) {}
  A(std::initializer_list<int>) {}
};

A a {0, 0}; // calls A::A(std::initializer_list<int>)
A b(0, 0); // calls A::A(int, int)
A c = {0, 0}; // calls A::A(std::initializer_list<int>)
A d {0, 0, 0}; // calls A::A(std::initializer_list<int>)

 

관련글 더보기