More than code

More Than Code
The efficiency of your iteration of reading, practicing and thinking decides your understanding of the world.
  1. 首页
  2. daily
  3. 正文

Daily C/C++ 是否要返回对象

2021年8月31日 507点热度 0人点赞 0条评论

Daily C/C++ 是否要返回对象

首先说句题外话,发现自己最近基本上都只是在写每日一题,在此之外的代码都写的很少了,要及时恢复

这篇文章说一下有关返回对象的一些做法,指的是我们平常的实现等,而不是函数的设计

有关函数要不要返回对象,我认为就是该用的时候用,平常的话自己那个顺手用那个就行

然后是正文,参考文章

一个用来返回的对象,应该是可移动构造/赋值的,一般也是可拷贝构造/赋值的。如果这样的对象同时可以默认构造,那么就称其为半正则的对象。

当我们在没有优化的情况下,会出现函数体内的返回值首先拷贝给临时对象,然后临时对象再拷贝给我们函数调用处的左值

目前的C++下,编译器会首先匹配移动构造函数,如果没有移动构造的话,再尝试匹配拷贝构造。所以上面说的流程也可以将拷贝转化成移动

不过对目前来说,编译器也不会蠢到进行两次移动,因为中间的这个临时变量没有任何意义,所以直接把函数内的返回值移动到我们的左值上就可以,这样就可以省去一次移动/拷贝

那么在有优化的情况下,即RVO,编译器会怎么操作呢?

在深度探索C++对象模型中可以看到,实际上编译器把我们的左值作为一个隐含的参数传入到函数中,然后直接在目标地址上进行构造,这样就省去了那一次的移动。所以现在可以只执行一次构造即可。

那么这里大家在看这篇文章

相信大家肯定有类似的疑问,我也有过,这里就解释一下

第一种方法就是我们平常用的方法,除了调用处的左值是一个右值引用。这里的代码是完全没问题的,如果把右值引用去掉,就用正常的值语义来接收的话,应该是会进行RVO的。但是这里用右值引用来接收这个参数,个人感觉也会优化,但不太确定。因为右值引用是延长了返回值的生命周期,所以貌似不会直接构造。

第二种方法是一种错误的方法,他返回了一个对局部变量的引用,这样当函数退栈的时候,对应的引用也会失效。

第三种方法和第一种方法结果相同,只不过使用了move来将返回值转化成一个将亡值,用于调用对应的移动构造函数来构造临时的返回值。然后再将临时的将亡值绑定到右值引用上,以延长生命周期。这里实际上是不需要做移动的,因为这会妨碍编译器做优化。我们手动的移动可能会导致多调用一次移动构造函数。

所以结论在返回的对象这块,暂时不需要考虑要显式的使用移动语义

如果返回的不是值语义的对象,比如工厂这样的,就用智能指针,RAII来维护

标签: c++
最后更新:2021年8月31日

sheep

think again

点赞
< 上一篇
下一篇 >

文章评论

取消回复

COPYRIGHT © 2021 heavensheep.xyz. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS