You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++11类成员初始化顺序问询:代码输出逻辑解析

Why Does This C++11 Class Initialization Produce That Output?

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:

  1. Initialize i1 first:
    Even though i1 has an inline default value (= 1), the constructor's initialization list (i1(i1_)) overrides this. So i1 is immediately set to the passed value 3.
  2. Initialize i2 next:
    i2 uses the result of initI2() for its initial value. At this point, i1 is already fully initialized to 3, so when initI2() prints and returns i1, it uses the correct value. That's why testInit::initI2::i1: 3 shows up first in your output.
  3. Run the constructor body:
    Only after all members are fully initialized does the constructor's function body execute. This is when testInit::testInit gets printed.
  4. Print values in main:
    Finally, main outputs i1 and i2, both of which hold the value 3.

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:02:01