【ChernoC++笔记】左值和右值

【85】【Cherno C++】【中字】C++的左值与右值

C++新特性:左值引用与右值引用

左值和右值#

❓什么是左值和右值?#

  • 大多数情况下,左值在等号左边,右值在右边。例如int i = 10;中变量i是左值,在内存中有实际的位置,通常有较长的生命周期;10是右值,没有存储空间,只是数字字面量,生命周期很短,通常是临时的。
  • 只能给左值赋值,不能写成10 = i;因为10没有位置,不能在10中存储数据。
  • 等号右边不一定是右值,例如int a = i;中,i就是之前的有实际位置的左值。

▶️当右值是函数的返回值#

int GetValue() {
	return 10;
}

int main() {
	int i = GetValue();
	GetValue() = 5; // error
}

GetValue()返回一个右值,它是一个临时值,没有存储位置。

如果写了GetValue() = 5;编译器会报错error: lvalue required as left operand of assignment ,也就是赋值的左操作数需要左值

左值引用#

▶️通过左值引用使GetValue()返回左值,它就可以被赋值。#

int& GetValue() {
	static int value = 10;
	return value;
}

int main() {
	int i = GetValue();
	GetValue() = 5; // fine
}

❓左值引用可以被右值赋值吗?#

void SetValue(int& value) {}

int main() {
	int i = 10;
	SetValue(i);
	SetValue(10); // error
}

不能使用SetValue(10),编译器报错:非常量引用的初始值必须为左值。

即,无法接受int& a = 10(使用右值来赋值左值引用)。

▶️通过常量引用解决该问题:#

const int& a = 10; // fine

实际上,编译器可能用实际的存储创建了该临时变量,然后赋值给引用,即

int temp = 10; // 创建了一个左值
const int& a = temp;

将上面的SetValue()参数也加上const,就可以同时接受左值和右值。

void SetValue(const int& value) {}

int main() {
	int i = 10;
	SetValue(i);  // fine
	SetValue(10); // fine
}

▶️字符串的例子#

std::string firstName = "Yan";
std::string lastName = "Chenikov";

std::string fullName = firstName + lastName;

firstName + lastName是一个右值:虽然字符串字面量是左值,但+操作符返回的是临时量,为右值。

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

int main() {
	std::string firstName = "Yan";
	std::string lastName = "Chenikov";
	std::string fullName = firstName + lastName;
	PrintName(fullName); // fine
	PrintName(firstName + lastName); // error
}

无法Print(firstName + lastName);,因为不能使用右值来给左值引用赋值。

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

int main() {
	std::string firstName = "Yan";
	std::string lastName = "Chenikov";
	std::string fullName = firstName + lastName;
	PrintName(fullName); // fine
	PrintName(firstName + lastName); // fine
}

参数加上const之后(即常量引用),可以兼容临时的右值和实际存在的左值变量。

右值引用#

❓写一个只接受临时对象的函数? ➡️➡️右值引用#

// 右值引用是两个&&
void PrintName(std::string&& name) {
	std::cout << name << std::endl;
}

int main() {
	std::string firstName = "Yan";
	std::string lastName = "Chenikov";
	std::string fullName = firstName + lastName;
	PrintName(fullName); // error
	PrintName(firstName + lastName); // fine
}

此时,PrintName(std::string&& name)函数可以接受右值,但不接受左值,编译器报错:无法将右值引用绑定到左值。

void PrintName(const std::string& name) {
	std::cout << "[lvalue] " << name << std::endl;
}

void PrintName(std::string&& name) {
	std::cout << "[rvalue] " << name << std::endl;
}

int main() {
	std::string firstName = "Yan";
	std::string lastName = "Chenikov";
	std::string fullName = firstName + lastName;
	PrintName(fullName); // [lvalue] YanChenikov
	PrintName(firstName + lastName); // [rvalue] YanChenikov
}

即使PrintName(const std::string& name) 也可以接受右值,但传入右值时,仍会选择第二个重载的函数PrintName(std::string&& name)

❓右值引用有什么用?#

优化技巧:处理右值引用时,可以检测到传入的是一个临时对象,从这个临时值中“偷”资源。

-->*移动语义

posted @   rthete  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
主题色彩
点击右上角即可分享
微信分享提示