跳至主要內容

C++

LincZero大约 3 分钟

C++

目录

右值引用

C++11参考:

本篇参考:

概要

C++11 标准对 C++ 语言增添了约 140 个新特性。右值引用是最重要的特性之一

右值引用不难,只不过是一种新的 C++ 语法。真正理解起来有难度的是基于右值引用引申出的 2 种 C++ 编程技巧,分别为移动语义和完美转发

C++左值和右值

  • 概念

    • 字面意思上理解,指的是以引用传递(而非值传递)的方式使用 C++ 右值
    • 一个表达式(可以是字面量、变量、对象、函数的返回值等)根据其使用场景不同,分为左值表达式和右值表达式
    • 确切的说 C++ 中左值和右值的概念是从 C 语言继承过来的
  • 区别

    • 值得一提的是,左值的英文简写为“lvalue”,右值的英文简写为“rvalue”。

      很多人认为它们分别是"left value"、"right value" 的缩写,其实不然。

      lvalue 是“loactor value”的缩写,可意为存储在内存中、有明确存储地址(可寻址)的数据。

      rvalue 译为 "read value",指的是那些可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据)。

  • 区分

    • 通常情况下,判断某个表达式是左值还是右值,最常用的有以下 2 种方法(只适用于大部分场景)
    • (1) 可位于赋值号(=)左侧的表达式就是左值;反之,只能位于赋值号右侧的表达式就是右值
    • (2) 有名称的、可以获取到存储地址的表达式即为左值;反之则是右值
int i=0;// i是左值, 0是右值

class A {
  public:
    int a;
};
A getTemp()
{
    return A();
}
A a = getTemp();   // a是左值  getTemp()的返回值是右值(临时变量)

左值引用 / 常量左值引用 / 右值引用

左值引用(普通引用&,C++98/03)

  • 使用&表示

  • 缺点:正常情况下只能操作 C++ 中的左值,无法对右值添加引用

    int num = 10;
    int &b = num; 	//正确
    int &c = 10; 	//错误
    

常量左值引用(C++98/03)

  • 其中const &也被称为万能引用,因为能为左值或右值添加引用

  • 缺点:无法对右值进行修改(实现移动语义时需要)

    int num = 10;
    const int &b = num;	//正确
    const int &c = 10;	//正确
    

右值引用(&&,C++11)

  • C++标准委员会在选定右值引用符号时,既希望能选用现有 C++ 内部已有的符号,还不能与 C++ 98 /03 标准产生冲突,最终选定了 2 个 '&' 表示右值引用。

  • 和声明左值引用一样,右值引用也必须立即进行初始化操作,且只能使用右值进行初始化

    int num = 10;
    //int && a = num;  //错误,右值引用不能初始化为左值
    int && a = 10;
    
  • 常量左值引用不同的是,右值引用还可以对右值进行修改

    int && a = 10;
    a = 100;
    cout << a << endl;
    
  • 支持常量右值引用

    const int&& a = 10;//编译器不会报错
    

补充

其实,C++11 标准中对右值做了更细致的划分,分别称为

  • 纯右值(Pure value,简称 pvalue) C++98/03 标准中的右值(本节中已经做了大篇幅的讲解)
  • 将亡值(eXpiring value,简称 xvalue )。 右值引用相关的表达式(比如某函数返回的 T && 类型的表达式)

对于纯右值和将亡值,都属于右值,读者知道即可,不必深究

移动语义、完美转发

详见移动构造函数一章