Renewed Structure
This commit is contained in:
108
Features-Cpp/C11/auto自动推导.MD
Normal file
108
Features-Cpp/C11/auto自动推导.MD
Normal file
@@ -0,0 +1,108 @@
|
||||
好,那我就帮你系统性地整理一份 **C++ 中 `auto` 与 lambda 函数的知识大全**,把语法细节、坑点、进阶用法都讲全,让你能用到开发级别。
|
||||
我会先分两部分:
|
||||
|
||||
1. `auto` 关键字大全
|
||||
2. Lambda 函数大全
|
||||
最后会给出它们的 **联合应用技巧**。
|
||||
|
||||
---
|
||||
|
||||
## 1. `auto` 关键字大全
|
||||
|
||||
### 1.1 基础概念
|
||||
|
||||
* **作用**:让编译器自动推导变量、函数返回值、模板参数的类型。
|
||||
* **推导时间**:编译期完成(不影响运行时性能)。
|
||||
* **核心限制**:
|
||||
|
||||
* 必须有初始化值(除非是函数返回类型或形参声明中)。
|
||||
* 不能推导为 **数组类型**(会退化为指针)和 **函数类型**(会退化为函数指针)。
|
||||
|
||||
---
|
||||
|
||||
### 1.2 基本用法
|
||||
|
||||
```cpp
|
||||
auto x = 10; // int
|
||||
auto y = 3.14; // double
|
||||
auto ptr = &x; // int*
|
||||
auto str = "Hello"; // const char*
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.3 `auto` 推导规则
|
||||
|
||||
假设初始化表达式类型为 `T`:
|
||||
|
||||
1. **普通变量**:直接推导为 `T`。
|
||||
2. **有引用**:
|
||||
|
||||
```cpp
|
||||
int a = 5;
|
||||
int& r = a;
|
||||
auto x = r; // int(引用被忽略)
|
||||
```
|
||||
3. **有 const**:
|
||||
|
||||
```cpp
|
||||
const int a = 5;
|
||||
auto x = a; // int(顶层 const 被忽略)
|
||||
```
|
||||
4. **保留引用和 const**:需要 `auto&` / `const auto&`
|
||||
|
||||
```cpp
|
||||
const int a = 5;
|
||||
auto& r = a; // const int&
|
||||
const auto& cr = a; // const int&
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.4 特殊形式
|
||||
|
||||
* **`auto*`**:明确推导为指针类型
|
||||
* **`decltype(auto)`**:保留完整类型信息(包括引用、const)
|
||||
|
||||
```cpp
|
||||
int x = 1;
|
||||
int& r = x;
|
||||
auto a = r; // int
|
||||
decltype(auto) b = r; // int&
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.5 在函数中
|
||||
|
||||
* **返回类型推导**
|
||||
|
||||
```cpp
|
||||
auto add(int a, int b) { return a + b; } // 返回 int
|
||||
```
|
||||
* **尾返回类型**
|
||||
|
||||
```cpp
|
||||
template<class T, class U>
|
||||
auto add(T a, U b) -> decltype(a+b) { return a+b; }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.6 常见坑
|
||||
|
||||
* **不同返回类型不能推导**:
|
||||
|
||||
```cpp
|
||||
auto test(bool b) {
|
||||
if (b) return 1; // int
|
||||
else return 1.5; // double
|
||||
} // ❌ 编译错误
|
||||
```
|
||||
* **列表初始化可能推导成 `std::initializer_list`**:
|
||||
|
||||
```cpp
|
||||
auto x = {1, 2, 3}; // std::initializer_list<int>
|
||||
```
|
||||
|
||||
---
|
138
Features-Cpp/C11/lambda函数.MD
Normal file
138
Features-Cpp/C11/lambda函数.MD
Normal file
@@ -0,0 +1,138 @@
|
||||
|
||||
## 2. Lambda 函数大全
|
||||
|
||||
### 2.1 基础概念
|
||||
|
||||
* **定义**:一种匿名函数对象(closure object)。
|
||||
* **语法结构**:
|
||||
|
||||
```cpp
|
||||
[捕获列表] (参数列表) -> 返回类型 { 函数体 }
|
||||
```
|
||||
* **返回类型可省略**:由 `return` 推导。
|
||||
|
||||
---
|
||||
|
||||
### 2.2 捕获方式
|
||||
|
||||
假设外部有 `int a; int b;`
|
||||
|
||||
| 捕获方式 | 含义 |
|
||||
| ----------- | ------------------- |
|
||||
| `[=]` | 按值捕获所有外部变量(只读) |
|
||||
| `[&]` | 按引用捕获所有外部变量 |
|
||||
| `[a]` | 按值捕获变量 `a` |
|
||||
| `[&a]` | 按引用捕获变量 `a` |
|
||||
| `[=, &b]` | 默认值捕获,单独指定引用捕获某些变量 |
|
||||
| `[&, a]` | 默认引用捕获,单独指定按值捕获某些变量 |
|
||||
| `[this]` | 捕获当前对象指针(隐式捕获成员变量) |
|
||||
| `[=, this]` | 按值捕获外部变量,同时捕获 this |
|
||||
|
||||
---
|
||||
|
||||
### 2.3 可变 Lambda (`mutable`)
|
||||
|
||||
* 按值捕获默认是 **不可修改捕获变量副本**
|
||||
* 加 `mutable` 可以修改副本
|
||||
|
||||
```cpp
|
||||
int x = 5;
|
||||
auto f = [=]() mutable { x += 1; }; // 修改的是副本
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.4 泛型 Lambda(C++14+)
|
||||
|
||||
```cpp
|
||||
auto add = [](auto a, auto b) { return a + b; };
|
||||
```
|
||||
|
||||
```cpp
|
||||
C++20
|
||||
auto add = []<class T>(const T& a, const T& b) { return a + b; };
|
||||
```
|
||||
|
||||
相当于模板函数。
|
||||
|
||||
---
|
||||
|
||||
### 2.5 返回类型
|
||||
|
||||
* **推导**(C++14+ 支持多返回类型推导一致性检查)
|
||||
* **显式声明**:
|
||||
|
||||
```cpp
|
||||
auto div = [](double a, double b) -> double { return a/b; };
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.6 存储与调用
|
||||
|
||||
* **立即调用**:
|
||||
|
||||
```cpp
|
||||
[]{ std::cout << "Hi\n"; }();
|
||||
```
|
||||
* **存储到变量**:
|
||||
|
||||
```cpp
|
||||
auto f = [](int x){ return x*x; };
|
||||
std::cout << f(5);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.7 转换为函数指针
|
||||
|
||||
* 仅无捕获 Lambda 可转换:
|
||||
|
||||
```cpp
|
||||
void (*fp)(int) = [](int x){ std::cout << x; };
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.8 在 STL 中用作比较器
|
||||
|
||||
```cpp
|
||||
auto cmp = [](int a, int b) { return a > b; };
|
||||
std::priority_queue<int, std::vector<int>, decltype(cmp)> pq(cmp);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. `auto` + Lambda 联合技巧
|
||||
|
||||
1. **类型保存**(比较器、回调等):
|
||||
|
||||
```cpp
|
||||
auto cmp = [](int a, int b){ return a < b; };
|
||||
std::set<int, decltype(cmp)> s(cmp);
|
||||
```
|
||||
|
||||
2. **推导返回类型**(泛型 + `auto`):
|
||||
|
||||
```cpp
|
||||
auto combine = [](auto a, auto b) { return a + b; };
|
||||
```
|
||||
|
||||
3. **模板中传 Lambda**:
|
||||
|
||||
```cpp
|
||||
template<class F>
|
||||
void run(F f) { f(); }
|
||||
run([]{ std::cout << "run!\n"; });
|
||||
```
|
||||
|
||||
4. **`decltype(auto)` 保持引用**:
|
||||
|
||||
```cpp
|
||||
auto getter = [](auto& c, size_t i) -> decltype(auto) { return c[i]; };
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
如果你愿意,我可以给你画一个 **`auto` 与 Lambda 的知识地图**,把所有用法和推导规则可视化,这样你看一次就能记住。这样对理解捕获机制和类型推导特别直观。
|
||||
你要我画吗?这样你可以一眼就看全流程。
|
Reference in New Issue
Block a user