22. 멤버 초기화 리스트의 실행 순서
난이도 중 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C++
// ============================================================================
// [언어 내부동작 문제] C++ - 멤버 초기화 리스트의 실행 순서
// ----------------------------------------------------------------------------
// 주제: 생성자의 멤버 초기화 리스트(member-init-list)에 나열한 순서와,
// 실제로 멤버가 초기화되는 순서가 항상 같을까?
// - 이 문제는 "결함을 고치는" 문제가 아니라, C++ 의 동작 원리를 설명하는 문제다.
// - 게임서버 코드에서 흔한 패턴: 세션/엔티티 클래스가 여러 멤버를 두고, 한 멤버의
// 초기값이 다른 멤버의 값에 의존하도록 초기화 리스트를 작성한다.
//
// 과제:
// 1) 아래 main 의 출력을 예측하라(어떤 순서로 어떤 값이 출력되는지).
// 2) 왜 그런 순서가 되는지, 무엇이 "실제로" 초기화 순서를 결정하는지 설명하라.
// 3) 아래 코드를 컴파일할 때 컴파일러가 경고를 낸다면 어떤 경고이고, 그 경고가
// 가리키는 위험은 무엇인지 설명하라.
// 4) 소멸자가 여러 개 있을 때 소멸 순서는 초기화 순서와 어떤 관계인지 설명하라.
// (먼저 직접 예측·설명을 적은 뒤 answer.md 와 대조할 것)
// ============================================================================
#include <cstdio>
class PacketBuffer {
public:
// 멤버 초기화 리스트에는 size_ 를 먼저, capacity_ 를 나중에 적었다.
// 그런데 size_ 의 초기값이 capacity_ 를 참조하도록 작성돼 있다. (A)
PacketBuffer(int capacity)
: size_(capacity_ / 2) // capacity_ 를 참조해서 size_ 를 정한다
, capacity_(capacity) // (B) 선언 순서와 리스트 작성 순서를 비교해볼 것
{
std::printf("capacity_=%d, size_=%d\n", capacity_, size_);
}
~PacketBuffer() {
std::printf("~PacketBuffer (capacity_=%d)\n", capacity_);
}
private:
// 선언 순서: size_ 가 capacity_ 보다 먼저 선언되어 있다.
int size_;
int capacity_;
};
class Session {
public:
Session(int cap)
: id_(1)
, buf_(cap)
, name_("session")
{
std::printf("Session ctor done: id=%d, name=%s\n", id_, name_);
}
~Session() {
std::printf("~Session\n");
}
private:
int id_;
PacketBuffer buf_;
const char* name_;
};
int main() {
std::printf("--- constructing Session ---\n");
Session s(64);
std::printf("--- destructing Session ---\n");
return 0;
} 내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.