右值引用和移动语义

右值引用

左值和右值

  1. 左值不是left value,右值也不是right value
  2. 左值(lvalue) 是“loactor value”的缩写,可意为存储在内存中、有明确存储地址(可寻址)的数据
  3. 右值(rvalue)译为 “read value”,指的是那些可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据)
  • 判断左值和右值的方法:
  1. 可以位于等号左边的值为左值,反之不能位于等号左边的值称为右值
  2. 有名称、可以获得到地址的的表达式即为左值,反之为右值

右值引用

  1. 左值引用如int &不能引用右值,但加上const int &可以引用右值,但不能修改
  2. 右值引用不能引用左值,即使加上const也不行
  3. 无论左值引用还是右值引用都必须在定义时初始化,且只能初始化一次(从一而终)
int x = 10;
int & y = x;   //左值引用
int && z = 10;  //右值引用
int & w = 10;  //错误的
const int & ww = 10;  //正确的,但不能修改值
int && x = 10;
x = 100;  //没问题
const int && x = 10;  //常量右值引用
x = 100;   //错误的
  1. 无论是左值引用还时右值引用,在不加const限定符时,可以修改,否则不能修改
  2. 右值虽然无法获取地址,但右值引用是可以获取地址的,该地址表示临时对象的存储位置
  3. 通过右值引用的声明使右值“获得新生”,其生命周期与右值引用类型变量的生命周期一样长,只要右值引用变量还活着,该右值临时变量将会一直活下去

移动语义

1.C++11引入了 移动语义:实际文件还留在原来的地方,只修改记录,移动语义避免了移动原始数据
2. 编译器是通过引用的类型(左值引用和右值引用),来决定是否需要进行复制:
(1)可定义两个函数,其中一个是常规的拷贝构造函数,它使用const左值引用作为参数,拷贝构造函数执行深复制
(2)另一个函数时移动构造函数,它使用右值引用作为参数,只调整记录,将所有权转移给新对象的过程中,移动构造函数可能修改其实参,因此移动构造函数的右值引用参数不应为const
3. 移动构造函数的基本用法:

class A
{
public:
    A(char* ptr) :m_p(ptr) { cout << "A(char * ptr)" << endl; }
    A(const A& obj)   
    {
        cout << "A(const A & obj)" << endl;
        int len = strlen(obj.m_p);
        m_p = new char[len + 1];
        strcpy_s(m_p, len+1, obj.m_p);
    }
    A(A&& obj)//移动构造函数
    {
        cout << "A(A && obj)" << endl;
        m_p = obj.m_p;
        obj.m_p = nullptr;
    }
    ~A()
    {
        cout << "~A()" << endl;
        delete[] m_p;
    }
private:
    char* m_p;
};
A func()
{
    char* ptr = new char[10]{ "hello" };
    A a1(ptr);
    return a1;
}
int main()
{
    A a2 = func();   //将调用移动构造函数,因为func()返回的是右值不是左值
    return 0;
}
  1. 适用于构造函数的移动语义也适用于赋值运算符,即移动赋值运算符
  2. 和移动构造函数相同,移动赋值运算符中的右值引用参数也不能为const
A & operator=(A && obj){
	if(this == &obj)
		return *this;
	m_p = obj.m_p;
	obj.m_p = nullptr;
	return *this;
}
  1. 若想让左值使用移动构造函数和移动赋值运算符有两种途径
    (1)使用static_cast<>将对象的类型强制转换为A&&
    (2)C++11提供了std::move(),在utility头文件中
    A a2 = static_cast<A&&>(a1);  //两种方式任选一种均可
    A a3 = std::move(a1);

参考文献

  1. C++11右值引用(一看即懂)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_46427273

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值