Skip to main content

Command Palette

Search for a command to run...

左值引用&右值引用

值类别和变量类型,生命周期

Published

左值引用

对于非const的左值引用,只能匹配左值。对于const的左值引用(也叫 常引用),可以匹配左值和右值

int a = 3;
int& ra = a; // 只能匹配左值
const int& cra = 10; // 可以匹配右值

右值引用

初始化

右值引用仅可使用 rvalue 进行初始化

Foo func2()
{
  Foo f1("AAA");
  return f1;
}

int main()
{
  int && r1 = 3; // 1. 引用字面量
  Foo && r2 = func2(); // 2. 引用临时变量(函数返回值)
  Foo && r3 = Foo("BBB"); // 3. 引用临时变量(匿名变量)

  Foo f("CCC");
  Foo && r4 = std::move(f); // 4. 引用std::move的强制左值

  return 0;
}

值类别(value category) 和 变量类型 (variable type)

值(value) 和 变量(variable) 是两个独立的概念。

  • 值 只有 类别 (category) 的划分,变量 只有 类型 (type) 的划分
  • 值 不一定拥有 身份 (identity),也不一定拥有 变量名(例如 表达式中间结果 i + j + k)

值类别可以分为五种: lvalue, xvalue, prvalue, glvalue, rvalue.

引用类型(Reference declaration)属于一种变量类型, ex: 左值引用,右值引用,常引用。

Foo&&类型只是指明变量类型,并不能区分左右值。就好像对于int i = 3; 一样,=的左右都是int类型,但是左侧的i是左值,右侧的3的右值(prvalue)。

右值引用初始化

右值引用和左值引用比起来,不同的地方在于初始化那一刻:右值引用必须通过右值来初始化。初始化完成之后,就没有什么特殊的了。

C++11有一个规则:右值引用类型(形如Foo&&)的表达式,有名字的是左值;没有名字的是右值。其实这也可以类比其他类型,命名变量(如局部变量、形参、全局变量)是左值;匿名变量(没有名字)是右值。

生命周期

通过 右值引用/常引用 初始化的右值,都可以将 生命周期扩展 (lifetime extension) 到 绑定该右值的 引用的生命周期

class Bar {
private:
    string s;
public:
    Bar(string a) : s(a) {
        cout << "Bar(string) " << s << endl;
    }
    ~Bar() {
        cout << "~Bar() " << s << endl;
    }
};
int main() {
    Bar("a");
    Bar&& rfb = Bar("b");
    cout << "end" << endl;
}

//    Output
//    Bar(string) a
//    ~Bar() a
//    Bar(string) b
//    end
//    ~Bar() b

对于a未被引用的右值, 在执行完当前行后,就会被析构。对于被rfb的右值引用的b,生命周期绑定至rfb的生命周期

ref

  1. https://www.yuanguohuo.com/2018/05/25/cpp11-rvalue-ref/
  2. https://murphypei.github.io/blog/2020/02/right-reference

More from this blog

<Programming with Types>随想: Chapter 2. Basic types

类型限制了一个变量可以接受的有效值的集合,对数据可以进行的操作,数据的意义。 空类型(The empty type) 根据类型的定义,类型定义了可以接受的有效值集合,那么这个集合有没有可能为空?答案是有可能的,TypeScirpt 的 never 就是这种类型。 需要注意的是,空类型不同与 void, 后者是有效值集合当中只有一个值,但这个值没有任何意义。而空类型的有效值集合本身是空的。 使用场景 控制流分析 在函数调用时,标志一个函数不会返回任何值: 在调用过程中抛出异常、死循环或者程序崩溃...

Mar 5, 2023
<Programming with Types>随想: Chapter 2. Basic types

精读《设计机器学习系统》-ch04: 训练数据

不同于 Chapter03 从系统的角度来处理数据,这一章从数据科学的视角来处理数据。这章的标题是“training Data”,而非“training dataset”,因为 数据集(dataset) 意味着有限(finite)和固定(stationary), 而现实生产环境中的 数据(data) 通常是 无限 并且 不固定 的。 抽样 抽样方法在 ML 项目的生命周期中无处不在,在这一节中,我们使用生成训练数据作为例子。 那为什么需要抽样?直接使用全部数据不可以吗? 首先,在现实世界中,并不...

Dec 10, 2022
精读《设计机器学习系统》-ch04: 训练数据
7

70 Talk

19 posts