int x;
class Point {
int x, y;
};
...
Point p;
위 상황에서 x 나 p의 멤버인 x, y는 어떤 경우에는 초기화가 보장되지만, 어떤 경우에는 초기화가 되지 않을 수 있음.
초기화 되지 않은 값을 읽는 것은 undefined behavior를 초래할 수 있다. 이는 프로그램을 멈추게 할 수도있고 반쯤은 랜덤한 값이 들어가서 디버깅도 힘들고 그런 상황이 나올 수 있음.
가장 간단한 룰은 초기화를 사용되기 전에 하는 것
객체의 모든 멤버는 생성자에서 초기화 하기
int x = 0;
double d;
std::cin >> d; // 입력으로 초기
대입과 초기화를 헷갈리지 말자
// 대입 예시
TEST::Test(const std::string&name)
{
theName = name;
}
// 초기화 예시
TEST::Test(const std::string& name) : theName(name) {}
- c++의 규칙에서는 객체의 데이터 멤버는 생성자의 body 에 들어가기 전에 초기화된다.
- 초기화는 생성자의 body에 들어가기 전에 default constructor가 자동 호출되면서 이루어짐.
- 대입 기반 생성자는 기본 생성자를 호출하고 초기화 하고 그 위에 값을 대입해서 덮어쓰기가 되므로 낭비가 되는 것.
- 따라서 member initialization list를 사용하자.
- 읽는 사람의 혼란을 막기 위해 member initialization list 의 초기화 순서를 선언 순서와 일치 시키자 ( 매우 드물게 일어나는 초기화 순서 관련 버그도 예방할 수 있음 )
non-local static objects
초기화에서 남은 한 가지 문제는 다른 translation units에 정의된 non-local static objects의 초기화 순서임.
- static object : 생성이 된 이후 프로그램이 종료될 때 까지 존재하는 객체.
- 전역 객체
- 네임 스페이스 범위에 정의된 객체
- 클래스 내부에 static으로 선언된 객체
- 함수 내부에 static으로 선언된 객체
- 파일 범위에 static으로 선언된 객체
- 함수 내부에 선언된 static 객체는 local static objects 그 외는 non-local static objects
- translation unit
- 하나의 객체 파일을 생성하는 소스 코드 단위
- 기본적으로 하나의 소스 파일 (
.cpp)과 그에 포함된 모든 #include 파일의 조합으로 이해