프로그래밍/Effective c++

4. 객체를 사용하기 전에 반드시 그 객제를 초기화하자

CuriousBear 2016. 3. 10. 13:48
c++에는 초기화 규칙이 명확하다. 하지만 그 규칙 자체가 복잡하기 때문에 닥치고 초기화하자. 
비멤벼 객체에 대해서는 초기화를 손수 하고, 멤버 객체는 생성자에서 그 객체의 모든것을 초기화 하자. 

하지만 대입을 초기화와 헷갈려서는 안된다.

ABEntry::ABEntry(const std: :string& name , const std : :string& address, const std : :list& phones)
{
theName = name ;
theAddress = address;
thePhones = phones ;
numTimesConsulted = 0 ;
}

theName, theAddress 및 thePhones 의 경우 대입을 하는 것이지, 초기화를 하는 것이 아니다. ABEntry 생성자에 진입하기도 전에 이들 세 데이터의 기본 생성자가 호출되었다.
물론  numTimesConsulted는 기본 제공타입이기 때문에 대입되기 전에 초기화 되리라는 보장은 없다.

초기화 리스트를 쓰자.
ABEntry : : AB ltry( onst std: :string& name , const std : :string& address, const std : : list& phones)
: theName (name) ,
theAddress(address) ,
thePhones(phones),
numTimesConsulted(O)
{}

이렇게 하면 초기화 리스트에 들어가는 인자가 데이터 멤버에 대한 생성자의 인자로 쓰여서 이 값으로 초기화가 된다. 따라서 생성자를 불러서 초기화 한 뒤 이를 무의미하게 하는 대입연산을 하는 것 보다 훨씬 효율적이다.

객체를 구성하는 데이터의 초기화 순서
- 어떤 컴파일러를 막론하고 같다.
1. 기본 클래스는 파생 클래스보다 먼저 초기화된다.
2. 클래스 데이터 멤버는 그들이 선언된 순서대로 초기화 된다.
맴버 초기화 리스트에 이들이 넣어진 순서가 다르더라도 초기화 순서는 그대로이다.


여러 번역 단위에 있는 비지역 정적 객체들의 초기화 순서 문제는 피해서 설계해야 한다 비지역 정적 객체를 지역 정적 객체로 바꾸면 된다.

class FileSystem { ... } ;

FileSystem& tfs (){
static FileSystem fs; // 지역 정적 객체를 정의하고 초기화합니다.
return fs ; / / 이 객체에 대한 참조자를 반환합니다
class Directory { ... } ;
Directory : : Directory ( params){
std : :size_ t disks = tfs () . numDisks ( ) ;
 }

이런식으로 지역 정적 객체로 바꾸면 원하는 순서로 초기화가 되도록 할 수 있다.