左值与右值、move与forward

本文深入解析C++中的左值与右值概念,探讨它们在赋值过程中的角色及意义,同时介绍move与forward在处理左值和右值时的作用,通过具体代码示例展示如何优化函数模板以提高代码效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

左值与右值

左值:

即等号左边的值。我们通常使用等号来赋值的时候,左边的是被赋值的对象。
那么显然,左值就是一个有名字、有内存的值。
比如:

int main()
{
	int a=1;
	int b=2;
	//这里的a、b均为左值
	return 0;
}

右值:

即等号右边的值。同样的,我们使用赋值的时候,等号右边的值通常是一个已知的、确定的值。
也就是说,右值是一个没有名字、没有内存的值,通常可以用来指一些临时量。
比如:

class MyString
{
public:
	MyString():p(nullptr){};
	~MyString()
	{
		delete p;
		p=nullptr;
	}
private:
	char *p;
};

MyString fun(char* p)
{
	return MyString(p);//这里返回的值就是一个临时量 它是右值
}
int main()
{
	int k=12;//这里的12也是右值
	return 0;
}

move与forward

move:

move ,底层实现实际上就是一个类型的强转,它会把一个左值强转成右值
在vector的push_back函数的实现中,我们需要针对左值和右值进行不同的存储操作。
然而,由于我们存储右值使用的符号本身是一个左值(比如上面的例子中,12是右值,但我们使用k来存储它的时候,k是一个左值),所以无法直接调用右值参数对应的函数,此时就需要使用move强转成右值。

void construct(T *p, const T& val)//对象的构造
{
	new(p) T(val);//定位new
}
void construct(T *p, T&& val)
{
	new(p) T(std::move(val));//为了能够匹配到右值引用参数对应的拷贝构造函数
}

void push_back(const T& val)//左值
{
	if(full())
		expand();
	construct(_last,val);
	_last++;
}
void push_back(T&& val)//右值
{
	if(full())
		expand();
	construct(_last,std::move(val));//为了匹配到右值参数对应的construct函数
	_last++;
}

forward:

上面的代码,我们可以看到为了实现面对两种参数的一种功能,我们使用了重复率很高的两段代码,在C++中,这种情况我们完全可以用函数模板进行优化。
forward,可以自动识别参数是左值还是右值。(释义为:类型的完美转发)
所以我们的代码可以优化为:

template<typename Ty>
void construct(T *p, Ty&& val)
{
	new(p) T(std::forward<Ty>(val));
}

template<typename Tk>
void push_back(Tk&& val)//传值时触发引用折叠
					    //& &&==>&		&& &&==>&& 
{
	if(full())
		expand();
	construct(_last,std::forward<Tk>(val));//自动识别val的类型
	_last++;
}```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值