4
4
5
5
# 自定义函数
6
6
7
+ ``` cpp
8
+ int square (int x) {
9
+ }
10
+ ```
11
+
7
12
## 调用函数
8
13
9
14
```cpp
@@ -35,38 +40,65 @@ void compute()
35
40
36
41
### 接住返回值
37
42
43
+ ## 函数的参数
44
+
45
+ ### 形参 vs 实参
46
+
47
+ ### 按引用传参 vs 按值传参
48
+
49
+ TODO:和 Python、Java 对比
50
+
51
+ ### C 风格变长参数
52
+
53
+ ## 模板函数
54
+
55
+ TODO:更多介绍函数
56
+
57
+ ## ` auto ` 神教
58
+
59
+ ### 变量 ` auto `
60
+
38
61
### 返回类型 ` auto `
39
62
40
- C++11 ` auto ` 可以用作函数的返回类型 ,但它只是一个** 占位 ** ,让我们得以后置返回类型。
63
+ C++11 引入的 ` auto ` 关键字可以用作函数的返回类型 ,但它只是一个“占位” ,让我们得以后置返回类型,并没有多大作用,非常残废 。
41
64
42
65
``` cpp
43
66
auto f () -> int;
44
67
// 等价于:
45
68
int f ();
46
69
```
47
70
48
- C++14 引入了函数** 返回类型推导** ,` auto ` 才算真正意义上的用做了函数返回类型,它会根据函数中的 ` return ` 表达式推导出函数的返回类型。
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 ` 表达式推导出函数的返回类型。
49
76
50
77
``` cpp
51
- int x = 1 ;
52
- auto f () {
53
- return x;
78
+ auto f (int x) {
79
+ return x * x; // 表达式 ` x * x ` 的类型为 int,所以 auto 类型推导为 int
54
80
}
55
81
// 等价于:
56
82
int f() {
57
- return x;
83
+ return x * x ;
58
84
}
85
+ ```
86
+
87
+ 如果函数中没有 `return` 语句,那么 `auto` 会被自动推导为 `void`,非常方便。
59
88
60
- // 如果函数中没有return语句,那么 `auto` 会被自动推导为 `void`
89
+ ```cpp
61
90
auto f() {
62
91
std::println("hello");
63
92
}
64
93
// 等价于:
65
94
void f() {
66
95
std::println("hello");
67
96
}
97
+ ```
98
+
99
+ 值得注意的是,返回类型用 ` auto ` 来推导的函数,如果有多条 ` return ` 语句,那么他们必须都返回相同的类型,否则报错。
68
100
69
- // 值得注意的是,返回类型用 `auto` 来推导的函数,如果有多条 `return` 语句,那么他们必须是相同的类型;否则报错
101
+ ``` cpp
70
102
auto f (int x) {
71
103
if (x > 0) {
72
104
return 1; // int
@@ -76,20 +108,56 @@ auto f(int x) {
76
108
} // 错误:有歧义,无法确定 auto 应该推导为 int 还是 double
77
109
```
78
110
79
- <!-- decltype( auto)... -->
111
+ `auto` 还有一个缺点是,无法用于“分离声明和定义”的情况。因为推导 ` auto` 类型需要知道函数体,才能看到里面的 `return` 表达式是什么类型。所以当 `auto` 返回类型被用于函数的非定义声明时,会直接报错。
80
112
81
- ## 函数的参数
113
+ ```cpp
114
+ auto f(); // 错误:看不到函数体,无法推导返回类型
82
115
83
- ### 形参 vs 实参
116
+ auto f() { // 编译通过:auto 推导为 int
117
+ return 1; // 1 是 int 类型的表达式
118
+ }
119
+ ```
84
120
85
- ### 按引用传参 vs 按值传参
86
-
87
- TODO:和 Python、Java 对比
121
+ 因此,` auto ` 通常只适用于头文件中“就地定义”的 ` inline ` 函数,不适合需要“分离 .cpp 文件”的函数。
88
122
89
123
### 参数类型 ` auto `
90
124
91
- ### C 风格变长参数
125
+ C++20 引入了 ** 模板参数推导 ** ,可以让我们在函数参数中也使用 ` auto ` 。
92
126
93
- ## 模板函数
127
+ TODO: 介绍
94
128
95
- TODO:更多介绍函数
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 * `
0 commit comments