'Programming/Effective C++'에 해당되는 글 2건

  1. 2015.01.28 객체 초기화
  2. 2015.01.28 const 사용법

1. 반드시 이니셜라이저를 통해서 초기화하자. 생성자에서 대입 연산으로 초기화 하는 것은 초기화가 아닌 대입이다(이미 객체의 생성자가 기본값이나 쓰레기값으로 초기화를 한 후 다시 초기화하는 꼴이된다)


2. 사용자 정의 자료형이 아닌 기본제공 자료형은 초기화가 될수도있고 안되어 있을 수도 있다.(int, char, double 등등)


객체를 구성하는 데이터의 초기화의 순서는 

1. 기본 클래스는 파생 클래스보다 먼저 초기화된다.

2. 클래스 데이터 멤버는 그들이 선언된 순서대로 초기화된다(이니셜라이저 초기화 순서는 상관없다)


정적 객체

1. 전역 객체

2. 네임스페이스 유효범위 안에서 정의된 객체

3. 클래스 안에서 static으로 선언된 객체

4. 함수 안에서 static으로 선언된 객체

5. 파일 유효범위에서 static으로 정의된 객체

이중 함수안에 있는 객체는 지역 정적 객체라 하고 밖에 있는 객체는 비지역 정적 객체라 한다.


번역단위

컴파일을 통해 하나의 목적 파일(Object File)을 만드는 바탕이 되는 소스 코드. 즉 #include 파일들까지 다 합쳐서 기계어로 번역하는 단위.


비지역 정적 객체의 초기화 순서는 개별 번역 단위에서 정해진다.(순서는 랜덤, 즉 정해져있지 않다.)


두 비지역 정적 객체의 초기화 과정에서 연관관계가 있을 시, 초기화에 문제가 생긴다(누가먼저 초기화될지 모르니까)


해결책

싱글톤 패턴처럼 레퍼런스를 반환시켜주는 함수를 각각 만들고 적용시킨다.


정리

1. 기본제공 타입의 객체는 직접 초기화한다. 경우에 따라 저절로 되기도 하고 안되기도 하기 때문에


2. 생성자에서는, 데이터 멤버에 대한 대입문을 생성자 본문 내부에 넣는 방법으로 멤버를 초기화하지 말고 멤버 초기화 리스트(이니셜라이저)를 이용한다. 그리고 초기화 리스트에 데이터 멤버를 나열할 때는 클래스에 각 데이터 맴버가 선언된 순서와 똑같이 나열한다.


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

   함수를 이용해 비지역 정적 객체를 지역 정적 객체로 바꿔 사용한다.( 싱글톤패턴, 레퍼런스 반환      함수 )  





'Programming > Effective C++' 카테고리의 다른 글

const 사용법  (0) 2015.01.28
Posted by 눈떠보니내무실
,

1. const 의 위치

void f1(const widget *pw)    //pw가 가리키는 값은 상수다.


void f2(widget const *pw)    //역시 pw가 가리키는 값은 상수다. 즉 위와 동일하다.


const vector<int>::iterator iter = vec.begin();    //iter는 T* const 처럼 동작한다.

*iter = 10;       //Ok. iter 가 가리키는 대상을 변경한다.

++iter;          //Error!, iter는 상수이기 때문에 변경이 불가능하다.


vector<int>::const_iterator iter = vec.begin    //iter는 const T*처럼 동작한다.

*iter = 10;       //Error!, iter 가 가리키는 대상은 상수다.

++iter;          //OK. iter 자체는 변수이므로 변경 가능.


2. 중복 코드 피하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class TextBlock
{
public:
    ...
    
    const char& operator[](size_t position) const //상수 객체를 위한 operator
    {
        return text[position];
    }
    
    char& operator[](size_t position) //비상수 객체를 위한 operator
                                                          //, 중복을 막기위해 상수버전을 호출한다.
    {
        return
          const_cast<char&>(           //반환 타입의 const를 날려버린다
             static_cast<const TextBlock&>(*this)[position]);  //static_cast를 통해 상수 operator를 
                                                             //불러온다.
            //*this는 TextBlock인데 이걸 const TextBlock로 형변환 함으로서 상수 객체를 위한 operator
            //를 불러올 수 있게 되는 것이다. 그냥 operator[] 를 부르면 자기자신을 계속부르는 무한루프에
            //걸리게 된다.
    }
    ......
};


1. const를 붙여 선언하면 컴파일러가 사용상의 에러를 잡아내는 데 도움을 준다. const는 어떤 유효범위에 있는 객체에도 붙을 수 있으며, 함수 매개변수 및 반환 타입에도 붙을 수 있으며, 멤버 함수에도 붙을 수 있다.


2. 컴파일러 쪽에서 보면 비트수준 상수성을 지켜야 하지만, 우리는 개념적인(논리적인) 상수성을 사용해서 프로그래밍 해야 한다.


3. 상수 멤버 및 비상수 멤버 함수가 기능적으로 서로 똑같게 구현되어 있을 경우에는 코드 중복을 피하는 것이 좋은데, 이때 비상수 버전이 상수 버전을 호출하도록 만들어야 코드의 낭비가 없어진다.(2번의 예처럼)









'Programming > Effective C++' 카테고리의 다른 글

객체 초기화  (0) 2015.01.28
Posted by 눈떠보니내무실
,