首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么std::move会阻止RVO?

为什么std::move会阻止RVO?
EN

Stack Overflow用户
提问于 2013-10-09 17:00:28
回答 2查看 20.9K关注 0票数 60

在许多情况下,当从一个函数返回一个local时,RVO就起作用了。然而,我认为显式使用std::move至少会在RVO没有发生时强制移动,但RVO仍然会在可能的情况下应用。然而,情况似乎并非如此。

代码语言:javascript
复制
#include "iostream"

class HeavyWeight
{
public:
    HeavyWeight()
    {
        std::cout << "ctor" << std::endl;
    }

    HeavyWeight(const HeavyWeight& other)
    {
        std::cout << "copy" << std::endl;
    }

    HeavyWeight(HeavyWeight&& other)
    {
        std::cout << "move" << std::endl;
    }
};

HeavyWeight MakeHeavy()
{
    HeavyWeight heavy;
    return heavy;
}

int main()
{
    auto heavy = MakeHeavy();
    return 0;
}

我用VC++11和GCC 4.71调试和发布(-O2)配置测试了这段代码。永远不会调用复制ctor。move ctor仅由调试配置中的VC++11调用。实际上,这些编译器看起来一切正常,但据我所知,RVO是可选的。

但是,如果我显式地使用move

代码语言:javascript
复制
HeavyWeight MakeHeavy()
{
    HeavyWeight heavy;
    return std::move(heavy);
}

移动函数总是被调用。因此,试图让它变得“安全”只会让它变得更糟。

我的问题是:

  • std::move为什么要阻止RVO?
  • 什么时候“抱最好的希望”并依赖RVO更好,什么时候应该显式使用std::move?或者,换句话说,如果没有应用RVO,我如何让编译器优化完成它的工作,同时仍然强制移动?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-09 20:28:42

允许复制和移动省略的情况见标准(N3690版)的第12.8§31节:

当满足某些条件时,允许实现省略类对象的复制/移动构造,即使为复制/移动操作选择的构造函数和/或对象的析构函数具有副作用。在这种情况下,该实现将省略的复制/移动操作的源和目标简单地视为引用同一对象的两种不同方式,并且该对象的销毁发生在这两个对象在没有优化的情况下将被销毁的较晚时间。这种拷贝/移动操作的省略,称为拷贝省略,在以下情况下是允许的(可以组合起来以消除多个拷贝):

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

的目标中,可以省略复制/移动操作

(我省略的两种情况指的是抛出和捕获异常对象的情况,我认为这对优化不太重要。)

因此,在return语句中,复制省略只能发生,如果表达式是局部变量的名称。如果您编写std::move(var),则它不再是变量的名称。因此,如果它应该符合标准,编译器就不能省略移动。

斯蒂芬T.Lavavej在Going Native 2013上谈到了这一点,并准确地解释了您的情况以及为什么要在这里避免std::move()。从38:04开始收看。基本上,当返回一个返回类型的局部变量时,它通常被视为一个右值,因此默认情况下允许移动。

票数 45
EN

Stack Overflow用户

发布于 2013-10-09 17:04:41

如果没有应用RVO,我如何让编译器优化完成它的工作,同时仍然强制执行move?

如下所示:

代码语言:javascript
复制
HeavyWeight MakeHeavy()
{
    HeavyWeight heavy;
    return heavy;
}

将回报转化为行动是强制性的。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19267408

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档