C++ 什么样的参数可以在返回语句中自动移动?

C++ 什么样的参数可以在返回语句中自动移动?,c++,c++11,C++,C++11,Andrew Koenig写了一篇文章,标题包含以下两个函数定义: string rev(string s) { reverse(s.begin(), s.end()); return s; // GCC-4.8 uses move constructor } string rev(string&& s) { reverse(s.begin(), s.end()); return s; // GCC-4.8 uses copy construct

Andrew Koenig写了一篇文章,标题包含以下两个函数定义:

string rev(string s) {
    reverse(s.begin(), s.end());
    return s; // GCC-4.8 uses move constructor
}

string rev(string&& s) {
    reverse(s.begin(), s.end());
    return s; // GCC-4.8 uses copy constructor
}
本文暗示第二个函数(与
常量字符串&
重载组合使用)比第一个函数效率更高。然而,当我用GCC-4.8测试它时,我看到的并不是这样。第一个函数在
return
语句中移动对象
s
,而第二个函数复制对象。如果我将第二个函数中的return语句更改为
returnmove(s),则在这两种情况下都将移动对象


问题:什么样的参数可以在
return
语句中自动移动?更具体地说,是否可以自动移动声明为非常量值引用的参数?

唯一可以通过return语句自动移动的是以下变量:

  • 是自动变量
  • 在函数的作用域中声明,以保证它们在函数退出时被销毁
  • 是值类型的变量
  • #3消除任何类型的引用。如果要从引用中移动,必须明确地说要从引用中移动

    然而,如果你想知道为什么后者会更有效率,那一定是因为移动的次数

    在第一种情况下,您可以复制/移动到函数参数
    s
    。用户必须将某些字符串复制或移动到参数中。然后参数的数据被移回

    在第二种情况下,您既没有复制也没有移动到函数参数中;它只是引用一个现有的对象。如果用户调用右值引用版本,则有一个超出参数范围的副本

    因此,第一个案例有一个拷贝/移动和一个移动,而恰恰是一个拷贝。因此,如果用户正在复制中的参数,则由于额外移动,第一种情况下的速度会变慢

    运动不是自由的。它可能很便宜(相对于复制),但不是免费的。两步比一步贵。如果用户调用
    常量&
    版本,则表示他们要求复制字符串。因此,他们得到了一份拷贝,然后采取了几乎肯定会被忽略的行动


    就我个人而言,我会权衡微小的效率提升与两次实现相同功能所带来的巨大头痛。在某些情况下,这可能是值得的。但是我当然不会这么做。

    “但是,当我用GCC-4.8测试它时,我看到的不是这个。”你是如何测试效率的?谢谢。问题实际上只是关于参数的自动移动操作。如果我理解正确,如果
    return
    语句中未使用
    std::move
    ,则第二个函数比第一个函数更差。你能把上面提到的规则添加到C++标准吗?