C++에서 ()
은 함수의 인자들을 정의하는데도 사용되고 일반적인 객체의 생성자를 호출할 때도 사용되기 때문에 컴파일러는 함수의 정의처럼 보이는 것들은 모두 함수의 정의로 해석한다. 따라서 아래의 코드처럼 생성자를 호출하였지만 함수의 정으로 해석되는 문제가 발생한다. 이를 해결하기 위해 균일한 초기화라는 것을 사용한다.
#include <iostream>
class A {
public:
A() { std::cout << "A 의 생성자 호출!" << std::endl; }
};
int main() {
A a(); // ?
}
해당 문법을 사용하기 위해서는 생성자를 호출할 때 ()
대신 {}
를 사용
{}
를 사용하면 암시적 타입 변환이 불가능
예시 코드
#include <iostream>
class A {
public:
A() { std::cout << "A 의 생성자 호출!" << std::endl; }
};
int main() {
A a{}; // 균일한 초기화!
}
코드 결과: A 의 생성자 호출!
{}
를 이용해 생성자를 호출할 때, 클래스의 생성자들 중에서 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}; }
주의점
{}
를 사용해 객체를 생성할 경우 생성자 오버로딩 시에 해당 함수가 최우선으로 고려됨{}
를 이용해 생성할 때 타입으로 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};