프로그래밍 일반 2014. 4. 10. 15:09

C++ 11 Non-static data member initializers

웹 컴파일러 링크 : http://melpon.org/wandbox/


C++ 98 에서는 오직 정수 타입의 정적 상수 멤버들 만이 클래스 내부에서 초기화 될 수 있었고 초기화 값은 반드시 상수 식이어야했다.

이러한 제약 조건은 컴파일 타임에 초기화가 될 수 있게 보장을 했다. 예를 들어


int var = 7;


class CTest {

    static const int m1 = 7; // 가능

    const int m2 = 7; // 오류 : static 아님

    static int m3 = 7; // 오류 : const 아님

    static const int m4 = var; // 오류 : 초기화값이 상수 식이 아니다

// const int var = 7 는 가능

    static const string m5 = "odd"; // 오류 : 정수 타입이 아닙니다

// ...

};


C++ 11 에서는 기본적으로 비 정적 데이터 멤버들도 클래스 안에 선언된 부분에서 바로 초기화가 가능하다. 


class CTest

{

private :

    int     m_iMember = 0;

};


는 아래 코드와 동일하다.


class CTest

{

public :

    CTest() : m_iMember(0) {}

    

private :

    int     m_iMember = 0;

};



이는 타이핑을 줄여줄뿐만 아니라 여러개의 생성자를 가지고 있는 클래스들을 사용할 때 도움이 된다.

많은 경우 모든 생성자가 특정 멤버에 대해 공통적인 초기화 값을 가지는 경우가 있다.


class C {

public:

    A(): a(7), b(5), hash_algorithm("MD5"), s("Constructor run") {}

    A(int a val) : a(a val), b(5), hash_algorithm("MD5"), s("Constructor run") {}

    A(D d) : a(7), b(Func(d)), hash_algorithm("MD5"), s("Constructor run") {}

  

private:

    HashingFunction hash_algorithm; // 모든 A 인스턴스들에 대해 암호화 된 해시가 적용된다

    std::string s;                  // 객체 생존사이클에 대한 상태를 나타내기 위한 문자열

    

    int a, b;

};


hash_algorithm 과 s 모두 디폴드 값이 있다는 사실을 위의 혼잡한 코드에서 쉽게 눈치채기는 어렵고 유지 보수시에 문제가 될 가능성이 있다.

대신 C++ 11 에서는 데이터 멤버들의 초기화를 다음과 같이 수행할 수 있다.


class A {

public:

    A(): a(7), b(5) {}

    A(int a val) : a(a val), b(5) {}

    A(D d) : a(7), b(Func(d)) {}


private:

    HashingFunction hash_algorithm{"MD5"};  // 모든 A 인스턴스들에 대해 암호화 된 해시가 적용된다

    std::string s{"Constructor run"};       // 객체 생존사이클에 대한 상태를 나타내기 위한 문자열

    

    int a, b;

};


만약 멤버가 클래스 내부와 생성자 양쪽에서 초기화 된다면 생성자에 의한 초기화만 수행된다. (즉, 디폴트를 오버라이드한다.)

따라서 아래와 같이 더 간단한 표현이 가능하다.

class A {

public :

    A() {}

    A(int a_val) : a(a_val) {}

    A(D d) : b(Func(d)) {}

private:

    HashingFunction hash_algorithm{"MD5"};  // 모든 A 인스턴스들에 대해 암호화 된 해시가 적용된다

    std::string s{"Constructor run"};       // 객체 생존사이클에 대한 상태를 나타내기 위한 문자열

    

    int a = 7;

    int b = 5;

};


참고 :

위의 링크를 타고가면 생각할 거리들이 많이 있다.