member initializer list

초기화 리스트는 본문보다 먼저 적용되지만, 실제 순서는 선언 기준이다

콜론 뒤 목록은 대입문이 아니라 기반 클래스와 멤버가 처음 값을 가지고 생성되는 자리다. 표시 순서가 아니라 기반 클래스, 멤버 선언 순서, 생성자 본문 순서로 객체가 완성된다.

실제 코드 형태
class Student : public Person {
std::string name;
int id;
const double gpa;
Course& course;
Student(std::string n, int i, double g, Course& c)
: Person("student"), name(n), id(i), gpa(g), course(c)
{ validate(); }
};
순서 함정

리스트를 : gpa(g), name(n), id(i)처럼 써도 실제 순서는 바뀌지 않는다

컴파일러는 클래스 안에 선언된 멤버 순서대로 초기화한다. 그래서 경고와 독해 비용을 줄이려면 초기화 리스트도 선언 순서와 맞춰 적는다.

생성 타임라인은 “목록에 적힌 순서”보다 언어 규칙을 따른다

storage -> base -> members -> body -> complete
1

저장 공간 확보

객체가 놓일 메모리가 준비된다.

2

기반 클래스 초기화

상속이 있으면 Person("student") 같은 기반 클래스가 먼저 만들어진다.

3

멤버 선언 순서 초기화

name, id, gpa, course 순서가 실제 순서다.

4

생성자 본문 실행

이미 만들어진 멤버를 검증하거나 불변식을 완성한다.

5

완성된 객체

생성자가 끝나면 public 함수가 기대하는 상태를 만족해야 한다.

6

소멸은 역순

생성이 끝난 멤버와 기반 클래스는 소멸 때 반대 순서로 정리된다.

본문 대입은 “이미 초기화된 뒤 값을 바꾸는 것”이라 필수 초기화를 대신하지 못한다

가능 주의 불가
일반 멤버 std::string name, int id
가능: 처음 값으로 생성 name(n), id(i)
가능하지만 대입 클래스 타입은 먼저 초기화된 뒤 다시 값이 들어갈 수 있다.
리스트가 기본값 의미 있는 시작 상태를 만들기 쉽고 불필요한 작업을 줄인다.
const 멤버 const double gpa
가능 gpa(g)처럼 생성 시점에 값을 확정한다.
불가 본문에서 새 값을 대입할 수 없다.
리스트 필수 값이 없으면 생성 자체가 실패한다.
참조 멤버 Course& course
가능 course(c)로 반드시 어떤 객체에 묶인다.
불가 참조는 나중에 다른 대상에 다시 묶을 수 없다.
수명 주의 참조 대상이 객체보다 오래 살아야 한다.
기본 생성자 없는 멤버·기반 인자가 필요한 타입
가능 필요한 인자를 초기화 리스트에서 전달한다.
불가 본문에 들어가기 전에 이미 초기화가 끝나야 한다.
컴파일 단계에서 결정 생성 방법이 없으면 객체를 만들 수 없다.