C++ 아이콘 제작자: Darius Dan - Flaticon
생성자를 호출하려다 함수를 만들어 버리거나 그런 실수를 방지할 수 있다.
그런데 ()와 달리 일부 암시적 타입 변환들을 불허한다.class A { public: A(int x) { std::cout << "A 의 생성자 호출!" << std::endl; } }; int main() { A a(3.5); // Narrow-conversion 가능 A b{ 3.5 }; // Narrow-conversion 불가 }
==> 따라서 {} 를 사용하면 위와 같이 원하지 않는 타입 캐스팅을 방지해서 미연에 오류를 잡아낼 수 있다.
class A {
public:
A(int x, double y) { std::cout << "A 생성자 호출" << std::endl; }
};
A func() {
return { 1, 2.3 }; // A(1, 2.3) 과 동일 }
// {}를 생성하지 않았다면 A(1, 2.3) 처럼 클래스를 명시해줘야지만
// {}를 이용할 경우 컴파일러가 알아서 함수의 리턴 타입을 보고 추론한다.
만약 ()로 생성자를 호출했다면 initializer_list는 생성되지 않는다.
initializer_list를 활용하면 컨테이너들을 간단하게 정의할 수 있다.
template <typename T>
void print_vec(const std::vector<T>& vec) {
std::cout << "[";
for (const auto& e : vec) { std::cout << e << " "; }
std::cout << "]" << std::endl;
}
template <typename K, typename V>
void print_map(const std::map<K, V>& m) {
for (const auto& kv : m) { std::cout << kv.first << " : " << kv.second << std::endl; }
}
int main() {
std::vector<int> v = { 1, 2, 3, 4, 5 };
print_vec(v);
std::cout << "----------------------" << std::endl;
std::map<std::string, int> m = { {"abc", 1}, {"hi", 3}, {"hello", 5}, {"c++", 2}, {"java", 6} };
print_map(m);
}
컨테이너를 초기화할 때 간단하게 {} 안에 원소들을 컨테이너에 맞게 넣어주면 된다.
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); // 일반 생성자 호출됨 ()로 생성했기 때문
A b{ 3, 1.5 }; // {}를 사용해서 initializer_list를 받는 생성자를 젤 우선적으로 생각함
}
최우선적으로 생각하여 해당 생성자를 선택하여 오버로딩 했지만
{}로 호출했기에 타입변환이 불허되기 때문에 컴파일 오류가 난다.전달되는 인자를 보면 일반 생성자가 호출되는게 맞다고 생각하지만
최우선은 initializer_list 를 이용한 생성자를 최대한 고려하기 때문하지만 아예 암시적 타입 변환이 일어나지 않는 경우는 해당 문제가 없다
A(std::initializer_list<std::string> lst) { std::cout << "초기화자 사용 생성자! " << std::endl; } }; A b{3, 1.5}; // 일반 생성자
위 경우 double이 string으로 변환될 수 없어서 그냥 오버로딩 후보군에서 제외된다.
C++ 17 부터 아래와 같이 두 가지 형태로 구분해서 auto 타입이 추론
•
auto x = {arg1, arg2...}
형태의 경우 arg1, arg2 ... 들이 모두 같은 타입이라면 x 는std::initializer_list<\T>
로 추론된다
•auto x {arg1, arg2, ...}
형태의 경우 만일 인자가 단 1 개라면 인자의 타입으로 추론되고, 여러 개일 경우 오류를 발생시킨다.
C++ 14 에서 추가된 리터럴 연산자를 통해 해결 ==> std::literals
auto list = {"a"s, "b"s, "c"s}; 와 같이 하면, initializer_list<std::string> 으로 추론
개인 공부 기록용 블로그입니다.
틀린 부분 있으다면 지적해주시면 감사하겠습니다!!