刷知乎引出的这篇博客:左值和右值

2024-06-04 19:54:55 浏览数 (2)

前言

晚上在电梯里刷知乎的时候,刷到move,于是便好奇多搜索点相关知识,其中左值和右值可算看懂了点了,于是趁着还没睡觉总结一波

内容

左值和右值网上很多通俗的说法是,左边的是左值,右边是右值,比如

代码语言:javascript复制
int a = 5;

a是左值,5是右值,这也是对的,但是呢,他不完全对

代码语言:javascript复制
int a = 10;
10 = a;

你会发现第二行10=a这就会报错

再比如

代码语言:javascript复制
int func()
{
	return 10;
}

a = 10; // yes
a = func(); // yes
func() = a;  // error

再比如

代码语言:javascript复制
int& func()
{
	static int test = 10;
	return test;
}

a = 10; // yes
a = func(); // yes
func() = a;  // func()是左值

你看懂了吗,只有它返回的是一个地址才能是左值,而之前直接return 10;这个10在内存中没有任何作用

我们再看

代码语言:javascript复制
void func(std::string& name)
{
	std::cout << name << std::endl;
}

int main()
{
	std::string firstName = "Neil";
	std::string secondName = "Zhu";
	std::string name = firstName   secondName;
	func(name);
	func(firstName   secondName);//编译器提醒这不是一个左值
}

此时编译器提醒func(firstName secondName);不是一个左值,因为虽然firstName和secondName是左值,但是他们两个临时形成的新字符串firstName secondName并不是一个有地址的东西,属于临时中间产生的而已,所以报错

但把代码改为:

代码语言:javascript复制
void func(const std::string& name)
{
	std::cout << name << std::endl;
}

int main()
{
	std::string firstName = "Neil";
	std::string secondName = "Zhu";
	std::string name = firstName   secondName;
	func(name);
	func(firstName   secondName);
}

我们发现就是在func里面用了const,这就可以了,虽然参数还是左值引用,但是新字符串firstName secondName这个临时右值也可以传进去

这就是你能看到为什么C 中有时候会有常量引用,因为它兼容临时的右值和实际存在的左值

再看一个

代码语言:javascript复制
void func(std::string&& name)
{
	std::cout << name << std::endl;
}

int main()
{
	std::string firstName = "Neil";
	std::string secondName = "Zhu";
	std::string name = firstName   secondName;
	func(name); // error
	func(firstName   secondName);
}

这时候func(name);会报错,因为参数是个右值引用,但是name是左值,所以没办法传进去

总结下就是左值引用在const时候可以绑定临时的右值和左值 但是右值引用只能绑定右值

这时候我们整合下代码,重载两个函数

代码语言:javascript复制
void func(const std::string& name)
{
	std::cout << name << std::endl;
}

void func(std::string&& name)
{
	std::cout << name << std::endl;
}

int main()
{
	std::string firstName = "Neil";
	std::string secondName = "Zhu";
	std::string name = firstName   secondName;
	func(name);
	func(firstName   secondName);
}

你会发现代码都正确,现在即使左值引用加了const,临时右值也可以穿进去,但其实firstName secondName走的还是右值引用自己的函数

下次再谈谈移动语义,看知乎的回答,move的作用是转移所有权,比如vector里面存了一些内容,之前直接复制的话,就很浪费空间,因为要一个个把内容复制过去,现在可以用move,直接把vector1的内容地址直接告诉vector2,让vector的指针直接指向这片空间的地址,但要注意的是之前vector1指针就空了

0 人点赞