C++:右值引用、移动语义move、完美转发forward

好家伙,右值还能引用呢?在我印象中,右值就是一个数、常量,不是个变量咋引用啊?

1 右值引用

左值lvalue(locator value) 存储在内存中,分配过内存,在内存中有地址的,有名字的数据。
右值rvalue(read value)存储在寄存器中,不一定可寻址的 ,没有名字临时的数据。
为什么要引入右值引用呢?
说是因为:实际开发中,需要对右值进行修改,如move

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int x = 5;

//左值引用:绑定到左值上的引用

    int& a = x;         //非常量左值引用: a引用x
    int& b = 5;         //wrong 非常量右值引用
    const int& c = x;   //常量 : 拷贝构造函数
    const int& d = 5;   //const左值引用可以绑定到右值上

//右值引用:绑定到右值上的引用

    int&& e = x;            //wrong 右值引用需要绑定到右值上
    int&& f = 5;            //非常量右值引用 : 移动语义
    const int&& g = x;      //wrong const右值引用不能绑定到左值上
    const int&& h = 5;      //const右值引用

    int&& i = x + 6;

    return 0;
}

在这里插入图片描述

2 移动语义move

move
int&& g = move(x); //将左值转化为右值
#include<bits/stdc++.h>
using namespace std;

class A {
public:
    int a;
    A(int p)
    {
        a = p;
        cout << "construct\n";
    }
    A(const A& aaa)
    {
        a = aaa.a;
        cout << "copy construct\n";
    }
    ~A()
    {
        cout << "deconstruct\n";
    }
};
A getTemp()
{
    return A(1);
}
int main()
{
    A&& obj = getTemp();   // getTemp()返回值是右值,可以使用右值引用,给临时变量起了个名字
    cout << obj.a << endl;
    return 0;
}

在这里插入图片描述
这篇[1]文章说的感觉不错
在这里插入图片描述
平时我们在写拷贝构造函数的时候也会使用常量引用来引用右值,减少一次拷贝。当时不明白为什么加const,现在大概是因为可以接受左值,也可以接受右值吧?

我现在觉得使用移动语义一方面是为了提高效率,在返回非引用的临时值时,会导致调用两次拷贝构造函数(里面可能是大量数组啥的,就很没有效率),而且临时对象拷贝完了就释放了,造成了没有意义的资源的申请与释放,要是能直接使用临时变量申请的资源就好了,这就是移动构造函数。
下面说的也很清晰:
临时变量是个右值,会优先调用移动构造函数,会使得直接将自己的指针指向对方的资源,让对方的指针为nullptr(指针不能共享,析构了内存也就不见了)
在这里插入图片描述
有些左值也是临时变量,生命期很短,为了好好利用资源,可以通过C++11新特性move将左值转化为右值。

#include<bits/stdc++.h>
using namespace std;

class A {
public:
    int* a;
    A(int p)
    {
        a = new int (p);
        cout << "construct\n";
    }
    A(const A& aaa)
    {
        a = aaa.a;
        cout << "copy construct\n";
    }
    A(A&& aaa)
    {
        a = aaa.a;
        aaa.a = nullptr; //置空
        cout << "move construct\n";
    }
    ~A()
    {
        delete a;
        cout << "deconstruct\n";
    }
};
A getTemp()
{
    return A(1);
}
int main()
{
    A obj = getTemp();   //getTemp()的返回值是右值(临时变量)
    cout << *obj.a << endl;
    return 0;
}
1. construct //创建临时变量p = A(1);
2. move construct //p(右值)移动构造无名临时变量tmp
3. deconstruct//p离开作用域析构
4. move construct//tmp移动构造obj
5. deconstruct //tmp析构
6. 1
7. deconstruct

在这里插入图片描述
————————————————————
上个厕所回来继续写
好吧,有点累了,明个和完美转发一起写

[1] [c++11]我理解的右值引用、移动语义和完美转发

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值