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
相关产品推荐
相关产品推荐

