Skip to content

Commit

Permalink
Create "C++ 左值与右值 左值引用与右值引用"
Browse files Browse the repository at this point in the history
  • Loading branch information
WangSimiao2000 committed Dec 12, 2024
1 parent 5710cc4 commit 7521dd1
Showing 1 changed file with 90 additions and 0 deletions.
90 changes: 90 additions & 0 deletions _posts/2024-12-12-Cpp-Lvalue-Rvalue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
title: C++ 左值与右值 左值引用与右值引用
date: 2024-12-12 13:20:00 +0800
categories: [笔记, C++]
tags: [C++, 左值, 右值, 左值引用, 右值引用]
---

## 左值与右值

```cpp
int a = 10; // a是左值, 10是右值
int *p = &a; // *p是左值, &a是右值
*p = 20;
```

左值: 表示某个特定内存位置的表达式
- 可以被赋值(可以出现在赋值号的左边和右边)
- 有明确的内存地址
- 例如: `int a = 10;` 中的a是左值

右值: 不能被赋值的表达式
- 不能出现在赋值号的左边
- 临时变量
- 例如: `int a = 10;` 中的10是右值

++i: i是左值, 返回的是自增之后的变量本身, 可以被赋值
i++: i是右值, 返回的是自增之前的变量, 不能被赋值

## 左值引用与右值引用

```cpp
int a = 10;
int& b = a;
```

左值引用: `int& b = a;`
- b是左值引用, a是左值
- 这里引用的`a`需要在之前已经定义过, 且`a`是左值, 即之前有: `int a = 10;`

```cpp
int&& c = 10;
```

右值引用: `int&& a = 10;`
- 这里引用的`10`是右值, 可以是临时变量
- 取右值引用时, 会先用一个临时变量保存右值, 然后将这个临时变量的地址赋给右值引用

右值本来是没有地址的, 但是编译器会通过临时变量保存右值, 可以取到这个临时变量的地址, 然后将这个地址赋给右值引用


```cpp
#include <iostream>

int Handle(int& l) {} // 接受左值引用
int Handle2(int&& r) {} // 接受右值引用

int main(){
int a = 10;
Handle(a); // 调用Handle函数, 传入的是左值
Handle(10); // 编译错误, 传入的是右值, 但是Handle函数需要的是左值
Handle2(10); // 调用Handle2函数, 传入的是右值
Handle2(a); // 编译错误, 传入的是左值, 但是Handle2函数需要的是右值
}
```
## 左值引用与右值引用的意义
右值有一个特殊的性质, 就是基本上只会被使用一次, 对于这种只会被使用一次的右值, 如果是比较大的数据(例如一个很大的数组), 如果用左值引用, 那么会拷贝一份数据, 但是如果用右值引用, 那么只会拷贝一个地址, 节省了内存
```cpp
#include <iostream>
#include <vector>
// 函数重载分别接受左值引用和右值引用
void Process(const std::vector<int>& v) {
std::cout << "Left value reference\n";
}
void Process(std::vector<int>&& v) {
std::cout << "Right value reference\n";
// 在这里可以直接操作 v 的资源,而不拷贝
}
int main() {
std::vector<int> v = {1, 2, 3};
Process(v); // 调用左值版本
Process(std::move(v)); // 调用右值版本
}
```

使用 std::move 将 v 转化为右值, 从而调用右值引用版本的函数, 这样就可以直接操作 v 的资源, 而不拷贝

0 comments on commit 7521dd1

Please sign in to comment.