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

C++中t3=t1+t2触发构造函数的原因及避免方法咨询

C++中operator+触发构造函数的原因及优化方案

问题描述

以下是测试用的C++代码:

#include<iostream>
using namespace std;

class Test
{
public:
int a;
Test();
Test(int b);
Test operator+(const Test t) const{Test ret; ret.a = t.a+a; return ret;}
};

Test::Test() {
    cout << "Null Constructor Called\n";
}
Test::Test(int b) {
    a=b;
    cout << "Assigned Constructor Called\n";
}

int main() {
    Test t1(1);
    Test t2(2);
    Test t3;
    t3 = t1+t2;
    return 0;
}

运行后输出:

Assigned Constructor Called
Assigned Constructor Called
Null Constructor Called
Null Constructor Called

疑问:代码中t3 = t1+t2;为什么会触发构造函数?有没有办法避免?

原因分析

t3 = t1+t2;触发构造函数的核心原因在operator+的实现里:

  • 执行t1 + t2时,会调用operator+函数,函数内部第一行Test ret;会直接创建一个Test类型的局部对象,这会触发无参构造函数,也就是输出里第四行"Null Constructor Called"的来源。
  • 另外,operator+的参数是const Test t,这里采用值传递方式,会调用编译器自动生成的默认拷贝构造函数(你没显式定义,所以编译器会生成),但默认拷贝构造不会输出任何内容,所以你看不到对应的日志。

优化方案(避免不必要的构造)

可以从以下几个方面修改代码,减少不必要的构造函数调用:

1. 优化operator+的实现,直接构造返回对象

把operator+里的局部对象创建逻辑改成直接返回构造好的对象,这样可以避免无参构造的调用,同时还能触发编译器的返回值优化(RVO),消除临时对象的拷贝:

Test operator+(const Test& t) const {
    return Test(t.a + this->a);
}

修改后,t1 + t2会直接调用带参构造函数创建返回对象,代替原来的无参构造+赋值操作,减少无参构造的调用次数。

2. 将operator+的参数改为引用传递

原来的operator+参数是值传递,会触发拷贝构造(虽然没有日志),改成const引用可以避免这一步拷贝:

Test operator+(const Test& t) const { ... }

这是C++运算符重载的常规写法,既避免拷贝,又保证不会修改传入的对象。

3. 直接初始化t3而非先默认构造再赋值

把main里的t3定义改成直接用t1+t2的结果初始化:

// 替换原来的 Test t3; t3 = t1+t2;
Test t3 = t1 + t2;

这样编译器可以利用拷贝省略(Copy Elision)优化,直接把t1+t2的结果构造在t3的内存空间里,避免默认构造和后续的赋值操作,进一步减少构造次数。

4. 显式定义移动构造函数(可选)

如果你的类后续有复杂成员,显式定义移动构造函数可以让返回临时对象时更高效,不过对于当前的简单类,RVO已经足够优化,这一步不是必须的:

Test(Test&& other) noexcept : a(other.a) {
    cout << "Move Constructor Called\n";
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 04:15:34