欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c++11学习笔记(3)- 左值、右值和右值引用

程序员文章站 2022-03-22 21:37:34
...

1.左值和右值

什么是左值,什么又是右值呢?先看一个例子
int a = b + c;
这里的 a 就是左值, 而 b+c 就是右值。
C++标准中没有明确的定义左值和右值,通常意义上我们对于左值和右值做出如下规定。

  • 可以取地址的、有名字的为 左值
  • 不能取地址的、没有 名字的就为 右值&(b+c) 无法编译通过,所以为右值。

右值有两个概念组成:将亡值纯右值

纯右值:用于辨识临时变量和一些不跟对象关联的值,比如,非引用的函数返回的临时变量的值为右值,一些运算表达式,如 1+2 产生临时变量的值也为右值;不跟对象关联的字面量也为右值如 2‘c’true;类型转换的返回值,lambda表达式也为右值。
将忘值:右值引用相关的表达式,这些表达是通常是将要被移动的对象(移为他用),比如右值引用 T&& 的函数返回值,std::move 的返回值,转换为 T&& 转换函数的返回值。

2.右值引用

  • 右值引用:对一个右值引用的类型,使用 T&& 表示。

下面就是一个右值引用的简单示例:

int b = 10, c = 20;
int a = b + c;

int& ac = a;
int&& bc = b + c;

std::cout << ac << std::endl;
std::cout << bc << std::endl;

输出结果为:
30
30

无论是左值引用还是右值引用,都必须立即初始化;因为引用本身并不具有绑定对象的内存,只是该对象的别名,左值是具体变量名的别名,右值是(匿名)变量名的别名。

3.右值引用的使用

1. 使用右值引用增长生命周期

我们首先来看一下下面的一个例子:

#include <iostream>
#include "stdlib.h"

class TestClass
{
public:
	TestClass(int number = 0):m_Number(number){
		std::cout << __FUNCTION__ << std::endl;
	}
	~TestClass() {}

	int m_Number = 10;
};

TestClass func(void) {
	TestClass testObj(20);
	return testObj;
}

int main(int argc, char** argv)
{
	TestClass && testClass = func();
	std::cout << testClass.m_Number << std::endl;
	
	system("pause");
	return 0;
}

运行结果为:
TestClass::TestClass
20

可见在调用函数 func 时,只产生了一次对临时变量的拷贝构造调用
TestClass && testClass = func();
func() 的生命周期结束了,但是通过右值引用,增长了它的生命周期,只要 testClass 对象还“活着”,那么它的值就一直存活下去。

2. 右值引用接受的对象

  • 通常右值引用是不能绑定左值的;
  • 非常量左值只能接受非常量左值对他进行初始化;
  • 常量左值是“万能”引用类型,它可以接受左值、常量左值、右值对它进行初始化

下表列出C++中所有引用类型可引用值得类型

引用类型 非常量左值 常量左值 非常量右值 常量右值
非常量左值引用 Y N N N
常量左值引用 Y Y Y Y
非常量右值引用 N N Y N
常量右值引用 N N Y Y

我面看一下下面的例子:

const bool &justment = true;

使用右值,并为其续命

const bool justment = true;

右值在表达式结束后被销毁