C++11中的右值引用和lambda表达式

右值引用

右值和左值是什么

  1. 普通类型的变量,有名字,可以取地址,都认为是左值。
  2. const修饰的常量,是左值
  3. 如果表达式运行结果是单个变量是一个引用则认为是左值。
  4. 如果表达式的运行结果是一个临时变量或者对象,认为是右值。

需要注意的是int a = 10;这一句里边,a是左值,而10是右值并且是纯右值,因为10只是一个符号,没有具体的空间
C++11对右值进行了严格的区分:
C语言中的纯右值,比如:a+b, 100
将亡值。比如:表达式的中间结果、函数按照值的方式进行返回

右值引用的概念

引用就是别名,而右值引用也是别名,但是只能引用右值。例如:

int add(int num1,int num2) {
	return num1 + num2;
}

int main() {
	// 函数按值返回的是一个右值,可以右值引用
	int&& num1 = add(2,5);

	// 10是一个纯右值,可以右值引用
	int&& num2 = 10;
}

引用与右值引用

  • 引用只能引用左值不能引用右值
  • const引用既可以引用左值又可以引用右值
  • 右值引用只能引用右值,一般情况下不能直接引用左值

在这里插入图片描述

完美转发

存在这样一种情况:

void Func(int x) {
}
template<typename T>
void PerfectForward(T t) {
	Func(t);
}

在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另外一个函数,这就叫做完美转发。

但是一般情况下,像上边这样写会导致右值丢失原来的右值的属性。

void Fun(int& x) { cout << "lvalue ref" << endl; }
void Fun(int&& x) { cout << "rvalue ref" << endl; }
void Fun(const int& x) { cout << "const lvalue ref" << endl; }
void Fun(const int&& x) { cout << "const rvalue ref" << endl; }
template<typename T>
void PerfectForward(T&& t) { Fun((t)); }
int main()
{
	PerfectForward(10); // rvalue ref
	int a;
	PerfectForward(a); // lvalue ref
	PerfectForward(std::move(a)); // rvalue ref
	const int b = 8;
	PerfectForward(b); // const lvalue ref
	PerfectForward(std::move(b)); // const rvalue ref
	return 0;
}

像上边的代码,本来期待的结果都写在调用的函数的后面,但是实际上代码运行的结果却……
在这里插入图片描述
所有函数参数都变成了左值。

为了解决这个问题达到完美转发,使用std::forward();函数

void PerfectForward(T&& t) { (Fun(forward(t))); }

结果如下:
在这里插入图片描述

lambda表达式

语法规则

lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type { statement }

  1. lambda表达式各部分说明
    [capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。
  2. (parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略
  3. mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。
  4. ->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。
  5. {statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。

关于捕捉列表:
捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用。

  • [var]:表示值传递方式捕捉变量var
  • [=]:表示值传递方式捕获所有父作用域中的变量(包括this)
  • [&var]:表示引用传递捕捉变量var
  • [&]:表示引用传递捕捉所有父作用域中的变量(包括this)
  • [this]:表示值传递方式捕捉当前的this指针
  • 捕捉列表可以有多个参数,中间以逗号间隔

举个栗子:

int main() {
	int a = 10;
	int b = 20;
	auto fun = [=](int a,int b) {return a + b; };
	cout << fun(10,10);
}

函数对象

函数对象又可以成为仿函数。就是在类里边重载operator()运算符的类对象。
举个栗子:

class Test {
public:
	Test()
		:_x(0)
	{};

	int operator()(int num1,int num2,int num3) {
		return num1 * num2 * num3;
	}

private:
	int _x;
};

int main() {
	Test t;
	// 仿函数
	t(10, 20, 1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值