- 예전에는 클래스와 구조체의 초기화 방식이 일정하지 않았었다.
// C++11 이전 구조체 정의
struct CircleStruct{
int x, y;
double radius;
};
// C++11 이전 구조체 타입 변수 초기화
CircleStruct myCircle1 = {10, 10, 2.5};
// C++11 이전 클래스 정의
class CircleClass{
public:
CircleClass(int x, int y, double radius)
: mX(x),mY(y), mRadius(radius) {}
private:
int mX, mY;
double mRadius;
};
// C++11 이전 클래스 타입 변수 초기화
CircleClass myCircle2(10, 10, 2.5);
-
위와 같이 클래스는 (...), 구조체는 {...} 를 사용하였다.
-
하지만 유니폼 초기화를 따르기로 하여 C++11 이후 {...} 로 통일되었다.
// 모두 3이란 값으로 초기화
int a = 3;
int b(3);
int c= {3}; // 유니폼 초기화
int b{3}; // 유니폼 초기화
- 유니폼 초기화를 사용하면 **축소 변환(narrowing)**을 방지할 수 있다!
// 축소 변환 에러
void func(int i) {
// do something;
}
int main() {
int x = {3.14};
func({3.14});
}
- 추가로 동적으로 할당되는 배열을 초기화할 때도 적용할 수 있다.
int* pArray = new int[4]{0, 1, 2, 3};
// 클래스 맴버 배열을 초기화할 수도 있다.
class myClass{
public:
MyClass() : mArray{0, 1, 2, 3} {}
private:
int mArray[4];
};
- 단일 초기화는 std::vector 와 같은 표준 라이브러리 컨테이너에도 적용 가능하며 이는 추후에 소개할 예정
1. 복제 리스트 초기화 : T obj = {arg1, arg2, arg3, ...};
2. 직접 리스트 초기화 : T obj{arg1, arg2, arg3, ...};
-
C++17 부터는 auto 타입 추론과 관련하여 복제리스트와 직접리스트 초기화가 크게 달라졌다.
-
주의할 점! auto는 직접 리스트 초기화에 대해 값 하나만 추론한다!
// 복제 리스트 초기화
auto a = {11};
auto b = {11, 22};
// 직접 리스트 초기화
auto c {11}; // int
auto d {11, 22}; // 원소가 많다는 에러 발생
// 복제 리스트 초기화에서 중괄호 안의 원소는 반드시 타입이 모두 같아야 함.
auto b = {11, 22.33} // error
- 1.5 표준 라이브러리는 생략(나중에 자세히..)