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

为何通过构造函数返回对象时无临时对象?构造过程解析

关于Stonewt类构造函数返回对象的执行流程与临时对象疑问解析

嘿,我来帮你拆解这个问题——先从你给出的代码片段入手(我补全了缺失的部分以便分析),一步步梳理执行流程,再解释为什么你感觉不到临时对象的存在。

完整代码示例

#include <iostream>
using namespace std;

class Stonewt {
private:
    double pounds; // 假设类中包含该成员变量
public:
    // 拷贝构造函数
    Stonewt(const Stonewt & obj1) { 
        cout << "Copy constructor shows up." << endl; 
        pounds = obj1.pounds;
    }
    // 转换构造函数(double 转 Stonewt)
    Stonewt(double lbs) { 
        cout << "Construct object in lbs." << endl; 
        pounds = lbs;
    }
    // 析构函数
    ~Stonewt() { 
        cout << "Deconstruct object." << endl; 
    }
    // 友元重载减法运算符
    friend Stonewt operator-(const Stonewt & obj1, const Stonewt & obj2);
};

Stonewt operator-(const Stonewt & obj1, const Stonewt & obj2) {
    double pounds_tmp = obj1.pounds - obj2.pounds;
    return Stonewt(pounds_tmp); // 通过构造函数返回对象
}

一、构造函数返回对象的执行流程

假设我们在主函数中执行以下代码:

int main() {
    Stonewt a(10.5);
    Stonewt b(5.2);
    Stonewt c = a - b;
    return 0;
}

正常情况下(无编译器优化)的执行步骤是:

  • 构造对象a:调用Stonewt(double lbs),输出 Construct object in lbs.
  • 构造对象b:同样调用转换构造函数,输出相同内容
  • 进入operator-函数:计算得到pounds_tmp = 10.5 - 5.2 = 5.3
  • 创建临时对象:调用Stonewt(5.3),输出 Construct object in lbs.
  • 拷贝临时对象到c:调用拷贝构造函数,输出 Copy constructor shows up.
  • 临时对象析构:输出 Deconstruct object.
  • 程序结束,依次析构c、b、a:输出三次 Deconstruct object.

但实际运行时你很可能看不到第5、6步的输出,这就涉及到你第二个疑问的核心了。

二、为什么没有产生可见的临时对象?

这是因为C++编译器的返回值优化(Return Value Optimization, RVO)——这是标准允许的一种优化手段,目的是避免不必要的临时对象创建和拷贝开销。

具体到你的代码中:

  • 当operator-直接返回一个临时对象(return Stonewt(pounds_tmp);)时,编译器会跳过临时对象的创建,直接在调用方的目标对象(也就是c)的内存空间上构造这个返回对象。
  • 这种优化会完全省略拷贝构造函数的调用和临时对象的析构过程,所以你看不到对应的输出,也就感觉不到临时对象的存在。

如果你想验证优化前的完整流程,可以关闭编译器的RVO优化:

  • 对于GCC/Clang,编译时添加选项 -fno-elide-constructors
  • 对于MSVC,使用 /Od 禁用所有优化

此时就能看到拷贝构造函数和临时对象析构的输出了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:24:46