주간 팁 #61: 기본 멤버 초기화 (Default Member Initializers)
원래 게시일: 2013년 11월 12일 (TotW #61)
작성자: Michael Chastain (mec.desktop@gmail.com)
최종 업데이트: 2016년 10월
기본 멤버 초기화 선언하기
기본 멤버 초기화는 생성 시 멤버의 기본 값을 선언하며, 다음과 같은 형태로 작성됩니다:
class Client {
private:
int chunks_in_flight_ = 0;
};
이 기본 초기화 코드는 해당 클래스의 모든 생성자(심지어 C++가 자동으로 생성한 생성자 포함)로 전파됩니다.
이 방법은 데이터 멤버가 많은 클래스에 유용하며, 특히 bool
, int
, double
, 원시 포인터 같은 타입에 적합합니다.
기본 타입의 비정적 데이터 멤버는 초기화를 빠뜨리기 쉽기 때문입니다.
사실 모든 타입의 비정적 데이터 멤버에 대해 초기화를 선언할 수 있습니다.
기본 멤버 초기화는 간단한 구조체 선언에도 유용합니다. 이러한 구조체에는 사용자 정의 생성자가 없습니다:
struct Options {
bool use_loas = true;
bool log_pii = false;
int timeout_ms = 60 * 1000;
std::array<int, 4> timeout_backoff_ms = { 10, 100, 1000, 10 * 1000 };
};
멤버 초기화 덮어쓰기
클래스 생성자가 이미 기본 초기화 값을 가진 데이터 멤버를 초기화하는 경우,
생성자의 초기화 값이 기본 초기화 값을 덮어씁니다:
class Frobber {
public:
Frobber() : ptr_(nullptr), length_(0) { }
Frobber(const char* ptr, size_t length)
: ptr_(ptr), length_(length) { }
Frobber(const char* ptr) : ptr_(ptr) { }
private:
const char* ptr_;
// length_에는 기본 초기화 값이 있음
const size_t length_ = strlen(ptr_);
};
이 코드는 기존 방식으로 작성된 다음 코드와 동일합니다:
class Frobber {
public:
Frobber() : ptr_(nullptr), length_(0) { }
Frobber(const char* ptr, size_t length)
: ptr_(ptr), length_(length) { }
Frobber(const char* ptr)
: ptr_(ptr), length_(strlen(ptr_)) { }
private:
const char* ptr_;
const size_t length_;
};
여기에서 첫 번째와 두 번째 Frobber
생성자는 비정적 변수에 대한 초기화를 명시적으로 제공합니다.
따라서 이 두 생성자는 length_
의 기본 초기화 값을 사용하지 않습니다.
반면, 세 번째 Frobber
생성자는 length_
의 초기화를 명시하지 않았으므로, 기본 초기화 값이 사용됩니다.
초기화 순서
C++에서 모든 비정적 변수는 선언된 순서대로 초기화됩니다.
첫 번째와 두 번째 Frobber
생성자는 length_
에 대해 명시적으로 초기화 값을 제공하므로,
기본 멤버 초기화 값은 무시됩니다. 이 경우, 기본 초기화 값은 코드 생성에 기여하지 않습니다.
참고: 이전 문서에서는 기본 멤버 초기화를 NSDMI(Non-Static Data Member Initializer)로 언급하기도 합니다.
결론
기본 멤버 초기화는 프로그램을 더 빠르게 만들어주지는 않습니다.
그러나 새로운 생성자나 데이터 멤버를 추가할 때 실수로 초기화를 빠뜨리는 버그를 줄이는 데 도움을 줍니다.
주의사항: 정적 멤버 초기화와의 차이점
비정적 멤버 초기화와 정적 멤버 초기화를 혼동하지 않도록 주의하세요:
class Alpha {
private:
static int counter_ = 0;
};
위 코드는 정적 멤버 초기화로, counter_
는 정적 변수입니다.
이는 비정적 멤버 초기화와 다르며, 정적 멤버 변수와 비정적 멤버 변수의 차이점과도 일맥상통합니다.