Skip to content

Commit d398a08

Browse files
committed
add auto and improve lambda more
1 parent 822cd7d commit d398a08

File tree

5 files changed

+479
-138
lines changed

5 files changed

+479
-138
lines changed

docs/auto.md

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# `auto` 神教 (未完工)
2+
3+
## 变量 `auto`
4+
5+
## 返回类型 `auto`
6+
7+
C++11 引入的 `auto` 关键字可以用作函数的返回类型,但它只是一个“占位”,让我们得以后置返回类型,并没有多大作用,非常残废。
8+
9+
```cpp
10+
auto f() -> int;
11+
// 等价于:
12+
int f();
13+
```
14+
15+
> {{ icon.fun }} 闹了半天,还是要写返回类型,就只是挪到后面去好看一点……
16+
17+
> {{ icon.detail }} 当初引入后置返回类型实际的用途是 `auto f(int x) -> decltype(x * x) { return x * x; }` 这种情况,但很容易被接下来 C++14 引入的真正 `auto` 返回类型推导平替了。
18+
19+
C++14 引入了函数**返回类型推导**`auto` 才算真正意义上能用做函数返回类型,它会自动根据函数中的 `return` 表达式推导出函数的返回类型。
20+
21+
```cpp
22+
auto f(int x) {
23+
return x * x; // 表达式 `x * x` 的类型为 int,所以 auto 类型推导为 int
24+
}
25+
// 等价于:
26+
int f() {
27+
return x * x;
28+
}
29+
```
30+
31+
如果函数中没有 `return` 语句,那么 `auto` 会被自动推导为 `void`,非常方便。
32+
33+
```cpp
34+
auto f() {
35+
std::println("hello");
36+
}
37+
// 等价于:
38+
void f() {
39+
std::println("hello");
40+
}
41+
```
42+
43+
值得注意的是,返回类型用 `auto` 来推导的函数,如果有多条 `return` 语句,那么他们必须都返回相同的类型,否则报错。
44+
45+
```cpp
46+
auto f(int x) {
47+
if (x > 0) {
48+
return 1; // int
49+
} else {
50+
return 3.14; // double
51+
}
52+
} // 错误:有歧义,无法确定 auto 应该推导为 int 还是 double
53+
```
54+
55+
`auto` 还有一个缺点是,无法用于“分离声明和定义”的情况。因为推导 `auto` 类型需要知道函数体,才能看到里面的 `return` 表达式是什么类型。所以当 `auto` 返回类型被用于函数的非定义声明时,会直接报错。
56+
57+
```cpp
58+
auto f(); // 错误:看不到函数体,无法推导返回类型
59+
60+
auto f() { // 编译通过:auto 推导为 int
61+
return 1; // 1 是 int 类型的表达式
62+
}
63+
```
64+
65+
因此,`auto` 通常只适用于头文件中“就地定义”的 `inline` 函数,不适合需要“分离 .cpp 文件”的函数。
66+
67+
## 参数类型 `auto`
68+
69+
C++20 引入了**模板参数推导**,可以让我们在函数参数中也使用 `auto`
70+
71+
TODO: 介绍
72+
73+
传统的,基于类型重载的:
74+
75+
```cpp
76+
int square(int x) {
77+
return x * x;
78+
}
79+
80+
double square(double x) {
81+
return x * x;
82+
}
83+
84+
int main() {
85+
square(2); // 4(调用 int 版重载)
86+
square(3.14); // 9.8596(调用 double 版重载)
87+
// 如果现在又需要 float 版呢?又得写一版重载,内容还是完全一样的,浪费时间
88+
}
89+
```
90+
91+
基于 `auto` 模板参数推导的:
92+
93+
```cpp
94+
auto square(auto x) {
95+
return x * x;
96+
}
97+
98+
int main() {
99+
square(2); // 4(auto 推导为 int)
100+
square(3.14); // 9.8596(auto 推导为 double)
101+
// 即使未来产生了 float 版的需求,也不用添加任何代码,因为是 square 是很方便的模板函数
102+
}
103+
```
104+
105+
## `auto` 推导为引用
106+
107+
TODO: 继续介绍 `auto`, `auto const`, `auto &`, `auto const &`, `auto &&`, `decltype(auto)`, `auto *`, `auto const *`

docs/functions.md

+2-106
Original file line numberDiff line numberDiff line change
@@ -54,110 +54,6 @@ TODO:和 Python、Java 对比
5454

5555
TODO:更多介绍函数
5656

57-
## `auto` 神教
57+
## main 函数的参数
5858

59-
### 变量 `auto`
60-
61-
### 返回类型 `auto`
62-
63-
C++11 引入的 `auto` 关键字可以用作函数的返回类型,但它只是一个“占位”,让我们得以后置返回类型,并没有多大作用,非常残废。
64-
65-
```cpp
66-
auto f() -> int;
67-
// 等价于:
68-
int f();
69-
```
70-
71-
> {{ icon.fun }} 闹了半天,还是要写返回类型,就只是挪到后面去好看一点……
72-
73-
> {{ icon.detail }} 当初引入后置返回类型实际的用途是 `auto f(int x) -> decltype(x * x) { return x * x; }` 这种情况,但很容易被接下来 C++14 引入的真正 `auto` 返回类型推导平替了。
74-
75-
C++14 引入了函数**返回类型推导**`auto` 才算真正意义上能用做函数返回类型,它会自动根据函数中的 `return` 表达式推导出函数的返回类型。
76-
77-
```cpp
78-
auto f(int x) {
79-
return x * x; // 表达式 `x * x` 的类型为 int,所以 auto 类型推导为 int
80-
}
81-
// 等价于:
82-
int f() {
83-
return x * x;
84-
}
85-
```
86-
87-
如果函数中没有 `return` 语句,那么 `auto` 会被自动推导为 `void`,非常方便。
88-
89-
```cpp
90-
auto f() {
91-
std::println("hello");
92-
}
93-
// 等价于:
94-
void f() {
95-
std::println("hello");
96-
}
97-
```
98-
99-
值得注意的是,返回类型用 `auto` 来推导的函数,如果有多条 `return` 语句,那么他们必须都返回相同的类型,否则报错。
100-
101-
```cpp
102-
auto f(int x) {
103-
if (x > 0) {
104-
return 1; // int
105-
} else {
106-
return 3.14; // double
107-
}
108-
} // 错误:有歧义,无法确定 auto 应该推导为 int 还是 double
109-
```
110-
111-
`auto` 还有一个缺点是,无法用于“分离声明和定义”的情况。因为推导 `auto` 类型需要知道函数体,才能看到里面的 `return` 表达式是什么类型。所以当 `auto` 返回类型被用于函数的非定义声明时,会直接报错。
112-
113-
```cpp
114-
auto f(); // 错误:看不到函数体,无法推导返回类型
115-
116-
auto f() { // 编译通过:auto 推导为 int
117-
return 1; // 1 是 int 类型的表达式
118-
}
119-
```
120-
121-
因此,`auto` 通常只适用于头文件中“就地定义”的 `inline` 函数,不适合需要“分离 .cpp 文件”的函数。
122-
123-
### 参数类型 `auto`
124-
125-
C++20 引入了**模板参数推导**,可以让我们在函数参数中也使用 `auto`
126-
127-
TODO: 介绍
128-
129-
传统的,基于类型重载的:
130-
131-
```cpp
132-
int square(int x) {
133-
return x * x;
134-
}
135-
136-
double square(double x) {
137-
return x * x;
138-
}
139-
140-
int main() {
141-
square(2); // 4(调用 int 版重载)
142-
square(3.14); // 9.8596(调用 double 版重载)
143-
// 如果现在又需要 float 版呢?又得写一版重载,内容还是完全一样的,浪费时间
144-
}
145-
```
146-
147-
基于 `auto` 模板参数推导的:
148-
149-
```cpp
150-
auto square(auto x) {
151-
return x * x;
152-
}
153-
154-
int main() {
155-
square(2); // 4(auto 推导为 int)
156-
square(3.14); // 9.8596(auto 推导为 double)
157-
// 即使未来产生了 float 版的需求,也不用添加任何代码,因为是 square 是很方便的模板函数
158-
}
159-
```
160-
161-
### `auto` 推导为引用
162-
163-
TODO: 继续介绍 `auto &`, `auto const &`, `auto &&`, `decltype(auto)`, `auto *`, `auto const *`
59+
TODO

docs/hello_world.md

-1
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,3 @@ int main()
134134
```
135135

136136
> {{ icon.tip }} 在我们以后的案例代码中,都会像这样注释说明,充当**就地讲解员**的效果。去除这些注释并不影响程序的正常运行,添加文字注释只是小彭老师为了提醒你每一行的代码作用。
137-

0 commit comments

Comments
 (0)