右值引用与模板学习笔记

右值引用与模板(一):左值、右值概念辨析与C++11右值引用

#include <iostream>
using namespace std;
int main1(void) {
	//左值:可以出现在赋值运算符左边
	//右值:所谓的数据
	/*int a = 10;
	int b = 20;*/
	//int c = a + b;
	//int a + b = 20;
	//左值:往往代表的一个存储空间
	//右值:由于这个a+b涉及到了计算机空间,仅仅能够在这个表达式
	//运行过程中存在
	/*__asm{
		mov eax,a
		mov ebx,b
		add eax,ebx
		mov c,eax
	}*/
	//右值是一个和运算过程相匹配的临时对象,这个临时对象在于其所对应的语句执行完毕之后,就销毁了
	//所以,我们无法从语法层面上直接访问。
	//左值是一个有名字,有固定地址的表达式
	//右值:仅仅匿名,没有固定地址的对象
	int a = 10;
	int& b = a;
	const int &c = a;//==》为左值a命名一个常量的别名c
	int x = 1000, y = 100;
	const int& i = x + y;//==>为右值x+y命名一个常量的别名i

	int tt = x + y;
	tt++;
	//i++;
	
	int&& right = x + y;
	right++;
	printf("%d", right);//通过所谓&&,形成的语法叫做右值引用
	//使得右值变成了一个与左值完全相同的持久对象

	system("pause");
	return 0;
}

右值引用与模板(二):右值引用与转移函数、参数优秀转发模板

class Foo {
public:
	Foo(int x){
		p = new int(x);
	}

	//如果一个临时对象,那么我们使用浅拷贝是巨大意义:
	//当我们需要具有“转移语义”的拷贝构造函数时
	//浅拷贝的效率意义就凸显了
	Foo(const Foo& r) {
		//this->p = r.p;//浅拷贝==>p和r.p指向了同样的一个地址
		p = new int;   //创建一个临时对象
		*p = *(r.p);   //深拷贝r.p指向的内容
	}

	//右值引用拷贝构造函数
	Foo(Foo&& r) {
		cout << "Foo(Foo&&)" << endl;
		p = r.p;//step1:简单的拷贝使得p和r.p指向了同一个空间
		r.p = nullptr;//step2:将r.p设为空指针,源对象放弃了资源所有权
	}
	~Foo()
	{
		if (p != NULL)
		{
			delete p;
		}
	}
	void show_p() {
		cout << p << " " << *p << endl;
	}
private:
	int *p;
};

Foo func() {
	Foo foo(100);
	return foo;
}


int main(void) {
	//浅拷贝
	/*Foo f1(50);
	Foo f2(f1);
	f1.show_p();
	f2.show_p();*/
	//end 浅拷贝

	Foo f(func());//资源所有权发生转移,资源位置没有改变而所属对象变化了
	f.show_p();
	system("pause");
	return 0;
}
void Myfunc(int  v) {
	cout << "Myfunc" << endl;
}
//转发模板
template<typename T>
void Tmp(T a) {
	Myfunc(a);
}
int main3(void) {
	int x = 1;
	Tmp(10);//10==》右值参数
	Tmp(x);//x==》左值传递
	//一定会进行所谓的临时对象的创建并且对数据进行拷贝,产生额外的开销
	system("pause");
	return 0;
}

右值引用与模板(三):make_pair

void RightFunc(int& v) {
	cout << "&函数调用" << endl;
}

void RightFunct(int&& v) {
	cout << "&&函数调用" << endl;
}

//转发模板
template<typename T>
void Tmp(T&& a) {
	RightFunc(a);
}

int main(void) {
	int x = 1;
	int &y = x;
	Tmp(x);//实参为左值
	Tmp(y);//实参为左值引用
	Tmp(100);//实参为右值
	system("pause");
	return 0;
}
//模板参数类型推导
//move:
//T&& move(T& val)
//接受一个参数val,然后返回这个参数右值引用
//左值: T&
//右值: T
//forward=>	T& ==> T&&

参数完美转发

#include <iostream>
using namespace std;

//参数类型为左值引用的目标函数
void Func(int &x) {
	cout << "左值引用" << endl;
}

//参数类型为右值引用的目标函数
void Func(int && x) {
	cout << "右值引用" << endl;
}

//参数类型为左值常引用
void Func(const int &x) {
	cout << "左值常引用" << endl;
}

//参数类型为右值常引用
void Func(const int && x) {
	cout << "右值常引用" << endl;
}

//参数完美转发
template<typename T>
void FuncT(T && a) {
	Func(std::forward<T> (a));//使用std进行类型推导
}


int main(void) {
	FuncT(10);//形参类型:右值
	int a;
	FuncT(a);//形参类型:左值
	FuncT(std::move(a));//形参类型为右值
	const int b = 8;
	FuncT(b);//形参类型为左值
	FuncT(std::move(b));//形参类型为右值 
	system("pause");
	return 0;
}
//STL make_pair make_unique=>临时对象效率问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值