c++的左值(lvalue),右值(rvalue),移动语义(move),完美转发(forward)

c++的左值(lvalue),右值(rvalue),移动语义(move),完美转发(forward)

c++的左值,右值 精辟总结

当一个对象被用作右值的时候,使用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)左值右值,完美转发参考文档

左值持久,右值短暂;move:显示地将一个左值转换为对应右值的引用类型,还可以获取绑定到左值上的右值引用,int&& rr3 = std::move(rrl); 使用move就意味着 除了对rrl赋值或销毁它外,我们不再使用它。

std::forward()与std::move()相区别的是,move()会无条件的将一个参数转换成右值,而forward()则会保留参数的左右值类型,可以使用std::forward实现 完美转发

移动语义解决了无用拷贝的问题:移动构造函数

右值引用:函数的返回值

int& 左值引用

int&& 右值引用

c++中无用拷贝的情况

/*类里面 没有移动构造函数
这样就会使用 copy construct function,会导致大量无用的 memory copy。
*/
class Test {
public:
    string desc;
    int * arr{nullptr};
    Test():arr(new int[5000]{1,2,3,4}) {
        cout << "default constructor" << endl;
    }
    Test(const Test & t) {
        cout << "copy constructor" << endl;
        if (arr == nullptr) arr = new int[5000];
        copy(t.arr,t.arr+5000, arr);
    }
    ~Test(){
        cout << "destructor " << desc << endl;
        delete [] arr;
    }
};

Test createTest() {
    return Test();
}

int main(){

    Test reusable;
    reusable.desc = "reusable";
    Test duplicated(reusable);
    duplicated.desc = "duplicated";

    Test t(createTest());
    t.desc = "t";

    cout<

运行结果

default constructor
copy constructor
default constructor
end
destructor t
destructor duplicated
destructor reusable

使用移动语义避免无用的拷贝

/*使用移动 construct function,避免无用的memory copy。
*/

class Test {
    public:
    string desc;
    int * arr{nullptr};
    Test():arr(new int[5000]{1,2,3,4}) {
        cout << "__default constructor" << endl;
    }
    Test(const Test & t) {
        cout << "__copy constructor" << endl;
        if (arr == nullptr) arr = new int[5000]; //在这里要将 t.arr 置为空,因为经过move之后,我们认为不在使用这个值了,避免在新的对象中把指针释放后,原来的对象中存在野指针的现象
        copy(t.arr,t.arr+5000, arr);
    }
    Test(Test && t): arr(t.arr) {
        cout << "__move constructor" << endl;
        t.arr = nullptr;
    }
    ~Test(){
        cout << "..destructor " << desc << endl;
        delete [] arr;
    }
};

Test createTest(string str) {
    Test rt;
    rt.desc = str;
    cout<

输出结果

__default constructor
reusable.arr 0x56521b946e70
__move constructor
reusable.arr 0
duplicated.arr 0x56521b946e70
rvalue--
__default constructor
createTest:0x7ffd092ea390
rt1.arr 0x56521b94c0b0
no rvalue--
__default constructor
createTest:0x7ffd092ea3c0
createTest:0x7ffd092ea3c0
rt2.arr 0x56521b950ee0
end
..destructor normalVal
..destructor rval
..destructor duplicated
..destructor reusable

左值引用右值引用

//左值引用和右值引用
void foo(const int & i) { cout << "const int & " << i << endl; }
void foo(int & i) {  cout << "int & " << i << endl; }
void foo(int && i) { cout << "int && " << i << endl; }
void foo(const int && i) { cout << "const int && " << i << endl; }
void main(){
    int i = 2;
    foo(i);
    foo(2);
    foo([]()->const int && {return 2;}());
}

完美转发

/*在main当中调用relay,Test的临时对象作为一个右值传入relay,在relay当中又被转发给了func,那这时候转发
给func的参数t也应当是一个右值。也就是说,我们希望:当relay的参数是右值的时候,func的参数也是右值;当
relay的参数是左值的时候,func的参数也是左值。
*/
class Test {
    public:
    int * arr{nullptr};
    Test():arr(new int[5000]{1,2,3,4}) {
        cout << "default constructor" << endl;
    }
    Test(const Test & t) {
        cout << "copy constructor" << endl;
        if (arr == nullptr) arr = new int[5000];
        copy(t.arr,t.arr+5000, arr);
    }
    Test(Test && t): arr(t.arr) {
        cout << "move constructor" << endl;
        t.arr = nullptr;
    }
    ~Test(){
        cout << "destructor" << endl;
        delete [] arr;
    }
};

template
void func(T t) {
    cout << "in func" << endl;
}

template
void relay(T&& t) {
    cout << "in relay" << endl;
    func(t);
}
//完美转发
template
void relay1(T&& t) {
    cout << "in relay " << endl;
    func(std::forward(t));
}

void main() {
    // relay(Test());
    // cout<

更多编程资料见公众号 xutopia77

c++的左值(lvalue),右值(rvalue),移动语义(move),完美转发(forward)

Original: https://www.cnblogs.com/xutopia/p/15782047.html
Author: xutopia
Title: c++的左值(lvalue),右值(rvalue),移动语义(move),完美转发(forward)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/611216/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • shell order

    1,与 “-a” : a是and if [ 条件1 -a 条件2 ] ;then shell order shell order … fi 2,…

    Linux 2023年5月28日
    0100
  • urandom和random区别

    linux中提供了 /dev/urandom 和 /dev/random 两个特殊设备来提供随机数。那么这两个文件有什么区别呢?要回答这个问题,先需要了解熵这个概念。 熵linux…

    Linux 2023年6月7日
    076
  • 安装win10和ubuntu双系统

    2019-06-22 ​ 最近找了一份新的工作,要用到linux,由于之前基本上没有接触过这方面的东西,所以今天捣鼓一下,安装win10和linux双系统,办公研发双不误。如果在安…

    Linux 2023年6月14日
    098
  • Java动态脚本Groovy,高级啊!

    前言:请各大网友尊重本人原创知识分享,谨记本人博客: 南国以南i 简介: Groovy是用于Java虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编…

    Linux 2023年6月14日
    0137
  • 软件测试基础理论

    软件基础的理论 一, 什么是软件产品 它是一个逻辑产品,没有实体,包括程序,文档和数据,需要通过终端设备才能体现出来功能和作用 二, 软件产品的中间过程文档 客户需求 &#…

    Linux 2023年6月7日
    085
  • mysql 8.0.20 忘记密码,修改密码

    由于mysql更新较快,8.0对比5.7很多操作有了变化,特别修改密码,和忘记密码这一块已经和以前完全不一样了。 一、 忘记密码 1、 在my.cnf 文件中添加skip-gran…

    Linux 2023年6月6日
    094
  • Linux NFS服务配置

    bash;gutter:true; 服务端配置: 1. 安装nfs-utils和rpcbind</p> <h1>yum install nfs-utils …

    Linux 2023年6月13日
    074
  • cpu idle 状态查看【原创】

    查看cpu idle的类型 cat /sys/devices/system/cpu/cpu0/cpuidle/state0/desc ARM WFI 查看cpu idle进入的次数…

    Linux 2023年6月8日
    0101
  • shell operator EOF shell 操作符 << <<<

    总结: 这些被叫做shell操作符 shell operator 主要分为 control operators和redirection operators < Origina…

    Linux 2023年5月28日
    092
  • 关于如何在window下执行SQLSERVER的定时备份

    引言 在使用SqlServer Express 版本的时候发现,这个版本不支持通过数据库的代理方式进行数据库的维护。 解决方案 使用SQL语句加windows任务计划的方式解决具体…

    Linux 2023年6月14日
    089
  • WEB自动化-03-Cypress 测试框架概述

    3 Cypress 测试框架概述 3.1 Cypress 默认文件结构 在Cypress安装完成后,其生成的默认文件目录如下所示: 3.1.1 Fixtures Fixture又称…

    Linux 2023年6月7日
    0107
  • 我的第一个博客

    我就是想试一试 .阿西吧 段狗是傻逼,段狗请看右边的看板娘 posted @2020-06-22 18:56 xiao-c 阅读(17 ) 评论() 编辑 Original: ht…

    Linux 2023年6月7日
    0128
  • Redis 持久化

    Redis 提供了一系列不同的持久性选项: RDB(Redis 数据库):RDB 持久性以指定的时间间隔执行数据集的时间点快照。 AOF(Append Only File):AOF…

    Linux 2023年5月28日
    075
  • 保罗·艾伦的故事

    上周,保罗·艾伦逝世。《财新周刊》约我写一篇纪念文章,发表在他们杂志上面 一些个人新闻:最近,我了解到我在2009年与之抗争的非霍奇金淋巴瘤已经复发。我已经开始治疗,我的医生很乐观…

    Linux 2023年6月14日
    0100
  • Xbox无法进入开发者模式

    从2020.09.01起,Xbox的dev mode app估计是证书过期或者其他系统配置问题,导致大量开发者无法进入开发者模式,具体如下图所示。 针对上述问题,可以通过微软预先设…

    Linux 2023年6月13日
    0237
  • 009 Linux 文件大小统计与排序( du于df和sort)

    01 du 与 df 作用与区别? – du(disk usage) df(disk free) 02 du 常用命令示例 03 sort 常用参数 04 常用组合 d…

    Linux 2023年5月27日
    0153
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球