首页 > 编程语言 >C++不要对函数返回值添加std::move()

C++不要对函数返回值添加std::move()

时间:2023-01-12 14:58:27浏览次数:62  
标签:std username move C++ user 返回值 构造函数

C++不要对函数返回值添加std::move()

References

  1. C++ 函数返回局部变量的std::move()问题?
  2. Return Statement Copy elision

Summary

  1. 编译器会进行返回值优化——复制省略(copy elision),局部对象直接创建在了需要函数返回值的地方。仅创建局部对象时调用构造函数。

  2. 如果对返回值添加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
  1. 确定会返回值优化的场景
  • 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
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

标签:std,username,move,C++,user,返回值,构造函数
From: https://www.cnblogs.com/qiangz/p/17046628.html

相关文章

  • Effective C++ 笔记
    EffectiveC++笔记Sec0Introduction本书的目的:如何有效运用C++,使软件易理解、易维护、可移植、可扩充、高效、并有预期行为提出的忠告分两类:一般性的设计策略,带有......
  • C++ 使用 new 创建二维数组
    C++使用new创建二维数组最直接的方法就是 ​​newT[M][N]​​​。返回的指针类型是 ​​T(*)[N]​​​,它是指向数组的指针,可以直接使用数组下标形式访问元素。释放内......
  • 【C++11】chrono库
    chrono是c++11中的时间库,提供计时、时钟等功能学习chrono,关键是理解里面精度、时间段、时间点的概念1.精度时钟节拍(时间精度),后面的时间段和时间点都是基于精度的计算......
  • 5月TIOBE编程语言:Python持续第一,C++将冲击前三
    新的TIOBE5月编程语言榜单出炉了,让我们一起看一下这次有哪些新看点:Python稳居第一,C++或将冲至Top3本次的榜单和4月相比没有明显变化,Top5依然是Python、C、Java、C++......
  • C++ STL的简单应用(vector容器专题)
    #include<iostream>#include<string>#include<stdlib.h>#include<vector>//#include<algorithm>usingnamespacestd;//vector容器的简单应用voiddemo1(){......
  • c++ unit test via gtest
    //model/book.h#pragmaonce#include<iostream>usingnamespacestd;classbook{public:book()=default;~book()=default;book(constbook&......
  • C++ 使用 new 创建二维数组
    1.直接创建C++使用new创建二维数组最直接的方法就是newT[M][N]。返回的指针类型是T(*)[N],它是指向数组的指针,可以直接使用数组下标形式访问元素。释放内存直接使......
  • 【教你学Qt桌面端开发】pt1:浅谈Qt:特色C++主义类库
    还在为头脑简单看不懂代码而发愁吗?还在为思想浅薄只会人云亦云、拾人牙慧、鹦鹉学舌而遭人鄙夷吗?《教你写代码》,从另一维度解读代码,让你成为见解独特的黑马观众。教你学Q......
  • C++ 扩展的显示类型转换
      ......
  • C++实现顺序队列(循环队列)相关操作代码
    #include<iostream>#include<cstdlib>usingnamespacestd;#defineMAXSIZE100#defineOK1#defineERROR0#defineOVERFLOW-1typedefintStatus;typedefintElemtype......