繁体   English   中英

编译器如何确定何时可以安全使用RVO?

[英]How does the compiler determine when is it safe to RVO?

编译器如何确定何时可以安全使用RVO? 不,我不是说右值,而是左值-如果我理解正确,RVO可以通过将目标地址“转发”给方法来工作,因此它返回目标地址而不是临时地址,然后复制/分配给目标。

但是编译器如何知道执行RVO是安全的? 如果左值中已经有一些数据,包括动态分配的资源,该怎么办? 在这种情况下,RVO可能会导致资源泄漏。 也许有一些规则指定是适用于执行优化还是坚持使用复制或赋值?

RVO只能初始化一个新对象,而不能重新分配现有对象。 因此,在这种情况下:

Thing thing = make_thing();

thing的地址传递给函数,函数将其初始化就位。

在这种情况下:

thing = make_thing();

RVO(通常)创建一个临时对象,然后将其分配给thing 只要可以正确分配类型,就不会有泄漏或类似问题。 由于它是一个临时的rvalue ,因此可以将其从中移走,这可能比复制更为有效。 如果类型是微不足道的可分配的,则也可以取消该分配-编译器在选择如何调用函数时将知道是否是这种情况。

返回值优化是复制省略的一种特殊情况。 如标准所述,它可能在以下情况下发生:

在具有类返回类型的函数的return语句中,当表达式是具有与函数返回类型相同的cv非限定类型的非易失性自动对象(函数或catch子句参数除外)的名称时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作

没有理由应该导致内存泄漏。 如果类在其构造函数中执行一些动态分配,则将对象直接构造到函数的返回值中时会发生这种情况。


根据您的评论(其中foo1foo2都构造T对象并返回它们):

T a = foo1();
a = foo2();

我们不仅在这里查看RVO,而且还在尝试从临时结构构造对象时发生另一种复制省略。

在第一行中,可以删除两个副本/动作:

  1. foo1返回构造的对象
  2. 复制返回的对象为a

也就是说,在构造的对象foo1可以直接在的位置创建a 如果构造动态分配一些对象,将只进行一次,为a对象。

在第二行中,可以删除单个复制/移动-仅从函数返回。 因此,将在函数的返回值中直接创建foo2构造的对象,然后将其复制/移动分配 a 不会忽略复制/移动任务。

然后,由复制/移动分配运算符来确保原始分配的资源被安全地丢弃,并且唯一剩余的资源是在foo2内部创建的资源。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM