必须是可修改的左值_C++ 左值引用和右值引用的区别

首先声明,在C++代码中,应该为了使用方便而优化,千万不要变成--为了复杂化代码而优化的虚伪的 C++ 哲学。

C++ 中绝大部分直接的赋值操作都是传拷贝,因为传拷贝很安全。

其实在绝大多数情况下,传拷贝 没有一点问题。

对于C++代码而言,我始终认为 安全性 才是最重要的,比如const, constexpr关键字,这些东西必须要学,必不可少,这是为了代码规范。

但是对于右值引用,我不认为它是一个必须要学的东西,而且很多时候,我觉得右值引用会让人感到困惑,并且把代码复杂化了。

代码1:

const string lover{ "girls" };
const string& chaser{ lover };

对于一般的代码而言,这样使用string没有任何问题,这只是一个普通的左值引用。

接下来,我将化身刘谦,给诸位带来一场魔术表演,我这个表演打算让一个string变量--凭空消失。

我并不打算直接修改这个变量,而是我只需要通过std::move

22714d2e674b5b895c9f524c2e3dc70b.png

别人问你,C++的艺术在哪里?C++的性能在哪里?你只需要向他展示这两行代码。

lover哪去了?凭空消失了?

不知道你懂了没有,C++在资源归属权的处理有着变态级别的控制。

拷贝就是拷贝,赋值也是拷贝,移动是移动,移动是资源易主。

再看一张图。

42f20d2663da2ec8298e9a056d0dd6eb.png

这串代码证明,在执行move操作后,string lover被清空了。

这个变量在内存中还存在,还可以使用,只是它的值为空。

By the way.

在使用std::move 之前 需要包含头文件 #include <utility>

代码3:

const string& hello(const string& str) {
	return str;
}


int main() {

	const string zyy = hello("great");
	
	return 0;
}

但是对于这样的代码,仍然存在优化空间,你能发现吗?

形参拷贝到返回值,返回值再拷贝到zyy。

好家伙,两次拷贝

移动的优势在于,移动不开辟额外的内存。

如下。

string&& hello(string&& str) {
	return move(str);
}

int main() {

	const string zyy{ hello("great") };
	return 0;
}

你也可以这样理解。

本来对于每个函数而言,执行函数时,一旦超过了它的作用域,局部变量就自动销毁了,但是我们通过一定的手段(右值引用)延长了“返回值的生命周期”,使得它没有被销毁,而是继续沿用下去。


const int& sum1(const int& a, const int& b) {
	return a + b;
}

int&& sum2(int&& a, int&& b) {
	return move(move(a) + move(b));
}

int main() {
	constexpr int a{ 1 };
	constexpr int b{ 2 };

	const int jkj = sum1(a, b);
	const int heh = sum2(3, 4);

	cout << "jkj: " << jkj << endl;
	cout << "heh: " << heh << endl;
	return 0;
}

对于以上代码,sum2的效率更高,因为它做了3次move操作,取代了copy操作。

实际上,我们可以只写一个sum函数重载它们。

但这仍然太复杂,对于每个函数我们至少要两个模板。

一个是const T& ,还有一个是T&&

std::forward可以让这两者统一,本质上仍然是函数重载.

forward以后有机会再讲。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值