반응형
0. 요약
- 기본 제공 타입의 객체는 직접 초기화.
- 경우에 따라 자동으로 되기도하고, 안되기도 함
- 멤버 초기화리스트를 이용해 초기화하자!
- 초기화리스트는 선언순서대로 하자!
- 여러 번역 단위에 있는 비지역 정적 객체들의 초기화 순서문제는 피해서 설계하자!
- 비지역 정적객체를 지역 정적객체로 바꾸면 됨!
1. 대입과 초기화의 차이
- 아래는 초기화가 아니라 대입!!
- 생성자 전에 초기화 되었고, 대입된다.
ABEntry::ABEntry(const std::string& _name, const std::string& _address){
this.theName = name;
this.theAddress = address;
this.numTimes = 0;
}
- 아래가 초기화
- 멤버 초기화 리스트 사용
ABEntry::ABEntry(const std::string& _name, const std::string& _address)
:theName(_name),
theAddress(_address),
numTimes(0)
{}
초기화가 대입보다 더 효율적
- 대입의 경우 초기화 후 바로 대입하므로, 앞의 초기화는 쓸모없는 행위가 됨
2. 초기화 규칙
- 기본 제공 타입은 멤버 초기화 리스트에 넣는 쪽으로 습관을 들이자!
- 매개 변수가 없더라도 0으로 초기화 하는 습관!
- 특히 상수, 참조자 형태의 데이터 멤버는 반드시 초기화 필요!
ABEntry::ABEntry()
: theName(),
theAddress(),
numTimes(0)
3. 생성자가 많을 때 팁
- 여러 생성자에서 초기화 리스트를 정의하면 불편함
- private 멤버 함수 하나를 만들어 초기화 하고, 모든 생성자에서 이 함수를 호출
- 데이터 초기값을 파일에서 읽거나,
- 데이터베이스에서 찾아오는 경우에 유용하게 사용 가능
- 하지만 이런 경우가 아니면 초기화 리스트가 효율적임
4. 초기화 순서
- 기본 클래스는 파생 클래스보다 먼저 초기화
- 클래스 데이터 멤버는 선언된 순서대로 초기화
- 초기화 리스트에서 순서가 달라져도 선언 순서대로 초기화
- 헷갈림 방지를 위해 초기화 리스트는 선언 순서와 맞추자!
5. 비지역 정적 객체의 초기화 순서
비지역 정적 객체의 초기화 순서
- 별개의 번역 단위에 정의된 비지역 정적 객체들의 초기화 순서는 '정해져 있지 않다'
정적 객체란?
- 생성된 시점부터 프로그램 끝날 때 까지 살아 있는 객체
- 정적 객체는 프로그램이 끝날 때 자동으로 소멸됨
- 아래 에서 4)를 지역 정적 객체, 4)를 제외한 나버지를 비지역 정적 객체라고 함
정적 객체 종류
- 1)전역 객체
- 2)네임스페이스 유효범위에서 정의된 객체
- 3)클래스 안에서 static으로 선언된 객체
- 4)함수 안에서 static으로 선언된 객체
- 5)파일 유효점위에서 static으로 정의된 객체
번역 단위란?
- 컴파일을 통해 하나의 목적파일을 만드는 바탕이 되는 소스 코드
- 기본적으로는 소스파일 하나며, 그 파일이 #include하는 파일까지 합쳐서 하나의 번역 단위가 됨
아래의 경우에 문제 발생
- 별도로 컴파일된 소스 파일이 두 개 이상 있고,
- 각 소스 파일에 비지역 정적 객체가 한 개 이상 있을 경우
문제 발생 이유
- 한쪽 번역 단위에 있는 비정적 객체가 초기화 되면서, 다른 쪽 번역 단위에 잇는 비지역 정적 객체를 사용하는데, 객체가 초기화 되어 있지 않을 수 있다!
예제
- tfs가 tempDir보다 먼저 초기화되어 있지 않으면, 에러 발생
// 객체 선언부
class FileSystem{
public:
std::size_t numDisks() const;
};
extern FileSystem tfs;
// 객체 사용부(다른 파일)
class Directory{
public:
Directory(params);
};
Directory::Directory(params){
std::size_t disks = tfs.numDisks();
}
// 실 사용부
Directory tempDir(params);
- 해결 방법
- tfs가 tempDir보다 먼저 초기화 되게는 할 수 없다.
- 설계적인 방법(Singleton)으로 해결!!
- 비지역 정적 객체를 하나씩 맡는 함수 선언
- 그 함수에서 객체 참조자를 반환
- 사용자 쪽에서는 함수호출을 하여 사용
- 비지역 정적 객체가 지역 정적 객체로 변경됨!
class FileSystem{...};
FileSystem& tfs(){
static FileSystem fs;
return fs;
}
class Directory{...};
Directory::Directory(params){
std::size_t disks = tfs().numDisks();
}
Directory& tempDir(){
static Directory td;
return td;
}
참고
- Effective C++
반응형
'C++ > Effective C++' 카테고리의 다른 글
[Effective C++] 6. 컴파일러가 만들어낸 함수가 필요없으면 확실히 이들의 사용을 금해버리자. (0) | 2021.03.15 |
---|---|
[Effective C++] 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자 (0) | 2021.03.15 |
[Effective C++] 3. 낌새만 보이면 const를 들이대 보자 (0) | 2021.03.15 |
[Effective C++] 2. #define을 쓰려거든 const, enum, inline을 떠올리자 (0) | 2021.03.15 |
[Effective C++] 1. C++를 언어들의 연합체로 바라보는 안목은 필수 (0) | 2021.03.15 |