1. 개요
오늘은 C++의 유니폼 초기화에 대해서 공부해보겠습니다.
2. 개념
유니폼 초기화(균일한 초기화)라고 말을 합니다. 아래의 코드를 봅시다.
#include <iostream>
class A
{
public:
A()
{
std::cout << "A 의 생성자 호출!" << std::endl;
}
};
int main()
{
A a();
}
성공적으로 컴파일을 하였으면?
놀랍게도 출력이 없습니다.
도대체 왜 이런 현상이 나오는것일까요?
A a(); //?
왜냐하면 사실은 위 코드가 A 의 객체 a를 만든것이 아니라, A 를 리턴하고, 인자를 받지 않는 함수 a 를 정의한 것이기 때문입니다.
왜냐하면 C++ 의 컴파일러는 함수의 정의처럼 보이는 것들은 모두 함수의 정의로 해석 하기 떄문입니다.
아래의 코드는 더욱 햇갈릴겁니다.
#include <iostream>
class A
{
public:
A()
{
std::cout << "A 의 생성자 호출!" << std::endl;
}
};
class B
{
public:
B(A a)
{
std::cout << "B 의 생성자 호출!" << std::endl;
}
};
int main()
{
B b(A());
}
성공적으로 컴파일을 할 경우
??? 아무런 출력이 없네요?
사실 위 코드를 보면 마치 b 라는 클래스 B 의 객체를 생성하는 것 같이 보이지만, 사실은 인자로 A 를 리턴하고 인자가 없는 함수를 받으며, 리턴 타입이 B인 함수 b를 정의한 것 입니다.
상당히 이상합니다. 이러한 문제가 발생하는 것은 () 가 함수의 인자들을 정의하는데도 사용되고, 그냥 일반적인 객체의 생성자를 호출하는데도 사용되기 떄문입니다.
그래서 우리의 C++는 11 버전 부터 균일한 초기화 즉 유니폼 초기화라는 것을 도입하게 됩니다.
3. 유니폼 초기화(균일한 초기화)
균일한 초기화 문법을 사용하기 위해서는 생성자를 호출하기 위해 ()를 사용하는 대신에 {} 를 사용하면 끝입니다.
#include <iostream>
class A
{
public:
A()
{
std::cout << "A 의 생성자 호출!" << std::endl;
}
};
int main()
{
A a{};
}
위와 같이 제대로 생성자가 호출되었음을 알 수 있습니다.
중괄호를 이용해서 생성자를 호출하는 문법은 동일합니다.
그냥 기존에 () 자리를 {} 로 바꿔주기만 하면 됩니다.
하지만 ()를 이용한 생성과 {}를 이용한 생성의 경우 한 가지 큰 차이가 있는데 바로 일부 암시적 타입 변환들을 불허하고 있다는 점 입니다.
#include <iostream>
class A
{
public:
A(int a)
{
std::cout << "A 의 생성자 호출!" << std::endl;
}
};
int main()
{
A a1(3.5);
A a2{3.5};
}
이러면?
이러한 컴파일 오류가 나옵니다.
보시다시피
A a1(3.5); // 가능
위 코드는 성공적으로 컴파일 되었고 a 에는 3.5의 정수 캐스팅 하여 3이 전달됩니다.
반면에
A a1{3.5}; // 불 가능
이친구는 불가능 합니다.
그 이유는 중괄호를 이용해서 생성자를 호출하는 경우 아래와 같은 암시적 타입 변환들이 불가능해집니다. 이들은 전부 데이터 손실이 있는 변환입니다.
- 부동 소수점 타입에서 정수 타입으로의 변환 (우리의 예시지요)
- long double 에서 double 혹은 float 으로의 변환, double 에서 float 으로의 변환.
- 정수 타입에서 부동 소수점 타입으로의 변환
등등이 있습니다.
따라서 {}를 사용하게 된다면, 위와 같이 원하지 않는 타입 캐스팅을 방지해서 미연에 오류를 잡아낼 수 있습니다.
{}를 이용한 생성의 또 다른 쓰임새로 함수 리턴 시에 굳이 생성하는 객체의 타입을 다시 명시 하지 않아도 됩니다.
4. Ref
'개발자 면접 공부 > C-C++' 카테고리의 다른 글
VTable 위치 파악 (0) | 2024.03.25 |
---|---|
초기화자 리스트(intializer_list) (0) | 2024.03.08 |
C++ vs C# (1) | 2024.02.18 |
Move Semantics (0) | 2023.10.29 |
스마트 포인터의 new와 make의 차이 (1) | 2023.10.03 |