C++11常用新特性——右值引用&&

右值引用&&

左值与右值

在C++的世界里,值被分类为左值和右值。简单地说,左值是那些在表达式之后仍然存在的对象,如变量。而右值是在表达式结束后不再存在的临时对象,如一些临时产生的值或对象。

我们可以通过一个简单的方法来鉴别它们:**如果你能够取得一个表达式的地址,那么它是左值;否则,它是右值。**例如,具有名字的对象总是左值,而字面量和一些表达式结果是右值。

为了更深入地理解右值,C++11将其进一步细分为纯右值将亡值。纯右值包括临时变量、某些运算表达式的结果和大部分字面量。将亡值则是与右值引用有关的表达式,它们常常涉及到移动操作。

不过,要记住的是,这两者的细微差别通常不会影响到大部分的应用。在实际编程中,我们经常将它们统一看作右值。

例如下面示例:

class Object {
    // some members...
};

Object createObject() {
    return Object();
}

int main() {
    Object obj;             // 'obj' 是一个左值
    Object&& tempObj = createObject(); // 'createObject()' 返回一个右值

    int a = 42;             // 'a' 是一个左值
    int&& rvalueRef = a + 5;   // 'a + 5' 是一个右值

    // 取地址示例
    Object* pObj = &obj;       // 可以,因为 'obj' 是左值
    // Object* pTempObj = &createObject();  // 错误,因为 'createObject()' 是一个右值

    return 0;
}

左值引用与右值引用

传统的C++引用(C++98)现在被称为左值引用,它允许我们为变量创建一个别名。而C++11引入了右值引用的概念,使我们能够为右值也创建一个别名。

右值引用的引入极大地丰富了C++的语义,特别是在涉及到移动语义时。通过使用右值引用,我们可以有效地"转移"资源,而不是复制,从而提高效率。

当我们给右值引用命名后,它其实变成了一个左值。

#include <iostream>
#include <utility> // for move

using namespace std;

class Data {
public:
    Data() { cout << "Constructor called!" << endl; }

    Data(const Data &) { cout << "Copy constructor called!" << endl; }

    Data(Data &&) { cout << "Move constructor called!" << endl; }
};

Data createData() {
    return Data();
}

int main() {
    // 左值引用示例
    int x = 10;
    int &lvalueRef = x; // 左值引用
    lvalueRef += 5;
    cout << "x: " << x << endl; // x现在是15

    // 右值引用示例
    Data &&rvalueRef = createData(); // 调用构造函数但不调用拷贝构造函数

    Data dataObj;
    Data copiedDataObj = dataObj; // 调用拷贝构造函数
    Data movedDataObj = move(dataObj); // 调用移动构造函数

    return 0;
}

当一个临时对象(右值)被绑定到一个右值引用时,它的生命周期会延长,与该右值引用的生命周期相同。

通常情况下,临时对象在表达式结束后就被销毁。但是,当它被绑定到右值引用时,这种销毁被延迟,直到该引用的生命周期结束。

引入右值引用的主要目的是实现移动语义。

左值引用只能绑定(关联、指向)左值,右值引用只能绑定右值,如果绑定的不对,编译就会失败。

但是,常量左值引用却是个奇葩,它可以算是一个万能的引用类型,它可以绑定非常量左值、常量左值、右值,而且在绑定右值的时候,常量左值引用还可以像右值引用一样将右值的生命期延长,缺点是,只能读不能改。

int a = 1;        
const int& ra = a;   // a是非常量左值。

const int b = 1;  
const int& rb = b;  // b是常量左值。

const int& rc = 1;   // 1是右值。
  • 总结

总结一下,其中T是一个具体类型:

  1. 左值引用, 使用 T&, 只能绑定左值。
  2. 右值引用, 使用 T&&, 只能绑定右值。
  3. 已命名的右值引用是左值。
  4. 常量左值,使用 const T&, 既可以绑定左值又可以绑定右值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Tian Meng

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

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

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

打赏作者

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

抵扣说明:

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

余额充值