이것만은 잊지 말자!
- 기본제공 타입의 객체는 직접 초기화, 경우에 따라 자동으로 되기도 안되기도 함
- 생성자에서는 데이터 멤버에 대한 대입문을 생성자 본문 내부에 넣는 방법으로 멤버를 초기화하지 말고 멤버 초기화 리스트를 즐겨 사용하자
초기화 리스트에 데이터 멤버를 나열할 때는 클래스에 각 데이터 멤버가 선언된 순서와 똑같이 나열하자
- 여러 번역 단위에 있는 비지역 정적 객체들의 초기화 순서 문제는 피해서 설계해야 함
싱글톤 패턴을 사용하여 비지역 정적 객체를 지역 정적 객체로 바꾸면 됨
객체의 일부는 값이 자동으로 초기화되는 것이 보장되지 않을 수 있으므로 미정의 동작을 방지하기 위해 항상 초기화하자
C++의 객체 초기화의 규칙이 정해져있지만 기억하기에는 너무 복잡함
대입과 초기화를 헷갈리지 말자
C++ 규칙에서 객체의 데이터 멤버는 생성자의 본문이 실행되기 전에 초기화돼야 함
대입할 경우 데이터 멤버의 기본 생성자가 호출된 뒤 할당 연산자가 호출되는 불필요한 연산 발생
멤버 초기화 리스트를 사용하여 복사 생성자를 호출하는 것이 더 효율적
class ABEntry
{
public:
// 대입
ABEntry(const int age)
{
_age = age;
}
// 초기화
ABEntry(const int age)
: _age(age)
{}
private:
int _age;
};
멤버 초기화
모든 멤버를 초기화하는 습관을 들여 초기화를 빼먹는 실수를 방지
상수이거나 참조자로 되어 있는 데이터 멤버는 대입이 불가능하므로 반드시 초기화돼야 함
각 생성자마다 데이터 멤버를 초기화하는 것이 중복된다면 private 멤버 함수에서 초기화하는 것도 고려
기본 클래스는 파생 클래스보다 먼저 초기화되고, (생성자 멤버 초기화 리스트에 다른 순서를 넣더라도) 데이터 멤버가 선언된 순서대로 초기화
따라서 버그를 방지하기 위해 멤버 초기화 리스트에 넣는 순서도 선언 순서와 동일하게 하자
비지역 정적 객체 초기화 순서는 개별 번역 단위에서 정해짐
정적 객체
전역 객체
네임스페이스 유효범위에서 정의된 객체
클래스 안에서 static으로 선언된 객체
함수 안에서 static으로 선언된 객체
파일 유효범위에서 static으로 정의된 객체
번역 단위
컴파일을 통해 하나의 object file을 만는 소스 코드
기본적으로 소스 파일 하나에 #include 하는 파일들까지 합쳐서 하나의 번역 단위
별개의 번역 단위에서 정의된 비지역 정적 객체들의 초기화 순서는 정해져 있지 않음
따라서 다른 번역 단위의 정적 객체를 사용할 경우 초기화되어 있지 않을 수 있음
함수에서 정적 객체를 선언하고 참조자를 반환하도록 구현(싱글톤 패턴)
멀티스레드 시스템에서는 초기화와 관련하여 race condition으로 동작에 장애가 생길 수 있으므로 멀티스레드 돌입 전 시동 단계에서 함수를 호출하여 초기화를 미리 하는 방법도 있음
class FileSystem { ... };
FileSystem& tfs()
{
static FileSystem fs;
return fs;
}
'C++ > Effective C++' 카테고리의 다른 글
Effective C++ 항목 9 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자 (0) | 2024.07.01 |
---|---|
Effective C++ 항목 8 예외가 소멸자를 떠나지 못하도록 붙들어 놓자 (0) | 2024.07.01 |
Effective C++ 항목 7 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자 (0) | 2024.07.01 |
Effective C++ 항목 2 #define을 쓰려거든 const, enum, inline을 떠올리자 (0) | 2024.06.21 |
Effective C++ 항목 1 C++를 언어들의 연합체로 바라보는 안목은 필수 (0) | 2024.06.21 |