什么样的参数可以在return语句中自动移动?

时间:2013-08-24 10:26:27

标签: c++ c++11

Andrew Koenig写了一篇标题为Some Optimizations Are More Important Than Others的文章,其中包含以下两个函数定义:

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
}

本文暗示第二个函数(与const string&重载相结合)比第一个函数更有效。然而,当我用GCC-4.8进行测试时,这不是我所看到的。第一个函数移动 s语句中的对象return,而第二个函数复制对象。如果我将第二个函数中的return语句更改为return move(s);,那么在这两种情况下对象都将移动

问题return语句中哪些参数可以自动移动?更具体地说,声明为非const rvalue-references的参数是否可以自动移动

1 个答案:

答案 0 :(得分:6)

可以通过return语句自动移动的唯一内容是:

  1. 是自动变量。
  2. 在函数范围内声明,以便在函数退出时保证它们被销毁。
  3. 是值类型的变量。
  4. #3删除了任何类型的引用。如果你想从参考文献中移动,你必须明确地说要从它移动。

    但是,如果你想知道为什么后者会更有效率,那就与行动次数有关。

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

    在第二种情况下,你既没有复制也没有进入函数参数;它只是引用一个现有的对象。如果用户调用右值参考版本,则您只有一个副本 out 参数。

    因此,第一个案例有一个副本/移动和一个移动,而不是一个副本。因此,如果用户正在复制参数,由于额外的移动,您的第一个案例将会变慢。

    运动不是免费的。它可能便宜(相对于复制),但它不是免费。 2次移动比1更贵。如果用户调用const&版本,这意味着他们要求复制字符串。所以他们得到一份副本,然后几乎肯定会被删除。

    就个人而言,我会将较小的效率收益与两次实施相同功能的重大问题进行权衡。在某些情况下,它可能是值得的。但我当然不会这样做。