禁用拷贝/移动消除时如何高效返回对象?给定代码是否有效?
编译禁用拷贝消除时的高效返回对象方案及代码分析
一、禁用拷贝消除后如何高效返回对象
在编译时禁用拷贝消除(比如GCC用-fno-elide-constructors参数)的场景下,要避免不必要的拷贝开销,常用方案有这些:
- 用
std::move触发移动构造:将函数内的局部对象通过std::move转为右值后返回,只要类实现了移动构造函数,就能用开销更低的移动操作替代拷贝。 - 直接返回临时对象:在返回语句中直接构造对象(比如
return Container();),此时返回的是临时右值,会触发移动构造而非拷贝构造。 - 传参修改而非返回:把目标对象以非const引用的方式传入函数,直接在函数内部修改对象状态,完全跳过返回时的构造开销。
二、给出的代码是否能避免不必要拷贝?
先看原代码:
Container getContainer() { Container c; return c; } int main() { Container&& container = getContainer(); }
这段代码无法避免不必要的拷贝,更算不上模拟拷贝消除:
- 在禁用拷贝消除的情况下,
getContainer()返回局部左值c时,必须先拷贝构造一个临时对象作为返回值,这个拷贝开销已经产生了。 - 后续
main中用右值引用绑定临时对象,只是延长了临时对象的生命周期,并没有消除之前的拷贝操作。
如果要优化这段代码,应该修改返回语句,用std::move把局部对象转为右值,触发移动构造:
Container getContainer() { Container c; return std::move(c); }
这样在禁用拷贝消除时,会调用移动构造函数(若类未定义移动构造,会退化为拷贝构造,所以建议为自定义类实现移动语义),大幅降低返回时的开销。
内容的提问来源于stack exchange,提问作者chakmeshma
相关产品推荐
相关产品推荐

