C++ 什么样的参数可以在返回语句中自动移动?
Andrew Koenig写了一篇文章,标题包含以下两个函数定义: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
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++标准吗?