generated from cotes2020/chirpy-starter
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5710cc4
commit 7521dd1
Showing
1 changed file
with
90 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 的资源, 而不拷贝 |