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

如何在构造函数的function-try-block中访问对象成员?

问题解答

核心结论

在构造函数的function-try-block的catch块中,绝对不能访问对象的任何非静态成员,包括通过this->name的方式——你的判断完全正确,此时对象尚未完成构造,生命周期未开始,访问成员属于未定义行为(UB),可能导致崩溃或不可预料的结果。

合法的解决方案

要在catch块中获取名字这类信息,唯一合法的方式是在初始化对象成员之前,将需要的数据保存到独立于对象的局部变量中。这个局部变量的生命周期不受对象构造失败的影响,可以安全地在catch块中使用。

方案1:拆分构造函数(推荐,适用于所有成员类型)

通过私有构造函数处理实际初始化,外层构造函数负责保存临时数据并捕获异常:

class MyClass {
public:
    MyClass(std::string param_name) {
        // 提前保存名字到独立临时变量,不受对象构造影响
        std::string temp_name = std::move(param_name);
        try {
            // 使用placement new在当前对象内存中调用私有构造函数完成初始化
            new (this) MyClass(std::move(temp_name), nullptr);
        } catch (const std::runtime_error& e) {
            std::cout << temp_name << " " << e.what() << std::endl;
            throw; // 必须重新抛出:对象未构造完成,不能进入可用状态
        }
    }

private:
    // 私有构造函数:负责实际成员初始化,可能抛出异常
    MyClass(std::string name, void*) 
        : name(std::move(name)),
          someOtherField(WillProbablyThrowSomeException()) {}

    std::string name;
    SomeOtherClass someOtherField;
};

方案2:函数体内的try块(仅适用于可默认构造的成员)

如果成员类型支持默认构造,可以放弃function-try-block,改用函数体内的普通try块手动初始化成员:

class MyClass {
public:
    MyClass(std::string param_name) {
        std::string temp_name = std::move(param_name);
        try {
            // 手动初始化成员(注意:不适用于const、引用或无默认构造的成员)
            name = std::move(temp_name);
            someOtherField = SomeOtherClass(WillProbablyThrowSomeException());
        } catch (const std::runtime_error& e) {
            std::cout << temp_name << " " << e.what() << std::endl;
            throw;
        }
    }

private:
    std::string name;
    SomeOtherClass someOtherField; // 需支持默认构造
};

关键规则补充

  1. 构造函数的function-try-block捕获的是初始化列表或函数体中抛出的异常,此时对象的生命周期并未开始,任何访问非静态成员的操作都是UB。
  2. catch块必须重新抛出异常(显式throw或隐式),否则编译器会自动重新抛出——未完成构造的对象不能被正常使用。

内容的提问来源于stack exchange,提问作者Morse

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 10:12:18