C++11类成员初始化顺序问询:代码输出逻辑解析
Let's start by restating your code and the observed output for clarity, then dive into the rules that explain what's happening.
Your Code
struct testInit { testInit(int i1_) : i1(i1_) { std::cout << "testInit::testInit" << std::endl; } int initI2() { std::cout << "testInit::initI2::i1: " << i1 << std::endl; return i1; } const int i1 = 1; const int i2 = initI2(); }; int main() { testInit ti(3); std::cout << "i1: " << ti.i1 << std::endl; std::cout << "i2: " << ti.i2 << std::endl; return 0; }
Observed Output
testInit::initI2::i1: 3 testInit::testInit i1: 3 i2: 3
The Key Rule: Member Initialization Order
The core principle here is class members are initialized in the exact order they are declared in the class definition—not the order they appear in the constructor's initialization list, and not the order of their inline default initializers. This rule hasn't changed since before C11, but C11's inline member initialization makes it easier to trip over if you're not paying attention.
Step-by-Step Breakdown
When you create testInit ti(3); in main, here's what happens in order:
- Initialize
i1first:
Even thoughi1has an inline default value (= 1), the constructor's initialization list (i1(i1_)) overrides this. Soi1is immediately set to the passed value3. - Initialize
i2next:i2uses the result ofinitI2()for its initial value. At this point,i1is already fully initialized to3, so wheninitI2()prints and returnsi1, it uses the correct value. That's whytestInit::initI2::i1: 3shows up first in your output. - Run the constructor body:
Only after all members are fully initialized does the constructor's function body execute. This is whentestInit::testInitgets printed. - Print values in
main:
Finally,mainoutputsi1andi2, both of which hold the value3.
A Critical Pitfall to Remember
If you had swapped the declaration order of i1 and i2 (declaring i2 first), this code would have undefined behavior: initI2() would access an uninitialized i1, leading to garbage values or crashes. Always make sure your constructor's initialization list (if used) aligns with the member declaration order to avoid such bugs.
内容的提问来源于stack exchange,提问作者malebranchi

