C++不要对函数局部变量返回值添加std::move()
C++不要对函数返回值添加std::move()
References
Summary
-
编译器会进行返回值优化——复制省略(copy elision),局部对象直接创建在了需要函数返回值的地方。仅创建局部对象时调用构造函数。
-
如果对局部对象返回值添加std::move(),调用了构造函数后,再先调用移动构造函数,再调用析构函数,反而加大了开销!
#include <iostream>
using namespace std;
class TestMove{
public:
TestMove(){
cout<<"Constructor"<<endl;
}
TestMove(const TestMove &&other){
cout<<"Move constructor"<<endl;
}
TestMove(const TestMove &other){
cout<<"Copy constructor"<<endl;
}
~TestMove(){
cout<<"Deconstrcutor"<<endl;
}
};
TestMove func(){
cout<<"no Move"<<endl;
TestMove testMove;
return testMove;
}
TestMove func_with_move(){
cout<<"with move"<<endl;
TestMove testMove;
return std::move(testMove);
}
int main(){
TestMove tm1 = func();
cout<<endl;
TestMove tm2 = func_with_move();
cout<<endl;
return 0;
}
no Move
Constructor
with move
Constructor
Move constructor
Deconstrcutor
Deconstrcutor
Deconstrcutor
- 确定会返回值优化的场景
- URVO(Unnamed Return Value Optimization):函数的所有执行路径都返回同一个类型的匿名变量
User create_user(const std::string &username, const std::string &password) {
if (find(username)) return get_user(username);
else if (validate(username) == false) return create_invalid_user();
else User{username, password};
}
// 作者:神奇先生
// 链接:https://www.zhihu.com/question/57048704/answer/151446405
// 来源:知乎
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- NRVO(Named Return Value Optimization):函数的所有路径都返回同一个非匿名变量,比如
User create_user(const std::string &username, const std::string &password) {
User user{username, password};
if (find(username)) {
user = get_user(username);
return user;
} else if (user.is_valid() == false) {
user = create_invalid_user();
return user;
} else {
return user;
}
}
//作者:神奇先生
//链接:https://www.zhihu.com/question/57048704/answer/151446405
//来源:知乎
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Note
首先 URVO 在 C++17 是强制的。不过 NRVO 不是强制,意味着有时不这么优化也是允许的。其次,若 return 的表达式是符合返回类型的左值,且编译器没有进行复制省略,那么标准(C++11 开始)也要求编译器先试图把表达式当右值,优先匹配移动构造函数(再匹配通常的复制构造函数),若失败的话则再将其当左值,匹配接受非 const 引用的复制构造函数。所以按照标准,上面的 std::move(a) 是不必要的(除非你希望强制调用移动构造函数),编译器在必要时会做同样的处理。
作者:暮无井见铃
链接:https://www.zhihu.com/question/57048704/answer/151453824
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。