File tree 2 files changed +100
-5
lines changed
2 files changed +100
-5
lines changed Original file line number Diff line number Diff line change @@ -12,7 +12,7 @@ TODO: println 参数演示
12
12
13
13
## 函数的返回值
14
14
15
- 函数可以没有返回值,只需要返回类型写 ` void ` 即可,这样的函数调用的目的只是为了他的副作用 (如修改全局变量,输出文本到控制台,修改引用参数等)。
15
+ 函数可以没有返回值,只需要声明函数时返回类型声明为 ` void ` 即可,调用这样的函数只是为了他的副作用 (如修改全局变量,输出文本到控制台,修改引用参数等)。
16
16
17
17
``` cpp
18
18
void compute ()
@@ -22,19 +22,62 @@ void compute()
22
22
```
23
23
24
24
> {{ icon.tip }} 对于没有返回值(返回类型为 ` void ` )的函数,可以省略 ` return ` 不写。
25
+
25
26
``` cpp
26
27
void compute ()
27
28
{
28
29
// 没问题
29
30
}
30
31
```
31
32
32
- > {{ icon.warn }} 对于有返回值的函数,必须写 return 语句,如果漏写,会出现可怕的未定义行为 (undefined behaviour)。编译器不会报错,而是到运行时才出现崩溃等现象,建议 GCC 用户开启 ` -Werror=return-type ` 让编译器检测此类错误。更多未定义行为可以看我们的[ 未定义行为列表] ( undef.md ) 章节。
33
+ > {{ icon.warn }} 对于返回类型不为 ` void ` 的函数,必须写 ` return ` 语句,如果漏写,会出现可怕的未定义行为 (undefined behaviour)。编译器不一定会报错,而是到运行时才出现崩溃等现象。建议 GCC 用户开启 ` -Werror=return-type ` 让编译器在编译时就检测此类错误,MSVC 则是开启 ` /we4716 ` 。更多未定义行为可以看我们的[ 未定义行为列表] ( undef.md ) 章节。
34
+ > {{ icon.detail }} 但有两个例外:1. main 函数是特殊的可以不写 return 语句,默认会自动帮你 ` return 0; ` 。2. 具有 co_return 或 co_await 的协程函数可以不写 return 语句。
33
35
34
36
### 接住返回值
35
37
36
38
### 返回类型 ` auto `
37
39
40
+ C++11 ` auto ` 可以用作函数的返回类型,但它只是一个** 占位** ,让我们得以后置返回类型。
41
+
42
+ ``` cpp
43
+ auto f () -> int;
44
+ // 等价于:
45
+ int f ();
46
+ ```
47
+
48
+ C++14 引入了函数** 返回类型推导** ,` auto ` 才算真正意义上的用做了函数返回类型,它会根据函数中的 ` return ` 表达式推导出函数的返回类型。
49
+
50
+ ``` cpp
51
+ int x = 1 ;
52
+ auto f () {
53
+ return x;
54
+ }
55
+ // 等价于:
56
+ int f () {
57
+ return x;
58
+ }
59
+
60
+ // 如果函数中没有return语句,那么 `auto` 会被自动推导为 `void`
61
+ auto f () {
62
+ std::println ("hello");
63
+ }
64
+ // 等价于:
65
+ void f () {
66
+ std::println ("hello");
67
+ }
68
+
69
+ // 值得注意的是,返回类型用 `auto` 来推导的函数,如果有多条 `return` 语句,那么他们必须是相同的类型;否则报错
70
+ auto f (int x) {
71
+ if (x > 0) {
72
+ return 1; // int
73
+ } else {
74
+ return 3.14; // double
75
+ }
76
+ } // 错误:有歧义,无法确定 auto 应该推导为 int 还是 double
77
+ ```
78
+
79
+ <!-- decltype(auto)... -->
80
+
38
81
## 函数的参数
39
82
40
83
### 形参 vs 实参
Original file line number Diff line number Diff line change @@ -117,8 +117,8 @@ int checkStdError(int ret) {
117
117
// return {};
118
118
// }
119
119
120
- template <class T >
121
- using expected = tl::expected<T, std::error_code>;
120
+ // template <class T>
121
+ // using expected = tl::expected<T, std::error_code>;
122
122
123
123
struct RAIIFile {
124
124
int fd;
@@ -133,8 +133,60 @@ struct RAIIFile {
133
133
// }
134
134
135
135
int main () {
136
- RAIIFile file{expectedStdError (open (" /tmp/test.log" , O_WRONLY)).value ()};
136
+ RAIIFile file{expectedStdError (:: open (" /tmp/test.log" , O_WRONLY)).value ()};
137
137
std::string s = " asasasas" ;
138
138
file.write (s).value ();
139
139
return 0 ;
140
140
}
141
+
142
+ namespace screenshot1 {
143
+
144
+ namespace std {
145
+ using namespace ::tl;
146
+ using namespace ::std;
147
+ }
148
+
149
+ std::expected<int , std::error_code> expectedStdError (int ret) {
150
+ if (ret == -1 ) {
151
+ return std::unexpected{std::error_code (errno, std::generic_category ())};
152
+ }
153
+ return ret;
154
+ }
155
+
156
+ struct File {
157
+ int fd;
158
+
159
+ explicit File (const char *path, int flags) {
160
+ fd = expectedStdError (::open (path, flags)).value ();
161
+ }
162
+
163
+ tl::expected<size_t , std::error_code> write (std::span<const char > buf) {
164
+ return expectedStdError (::write (fd, buf.data (), buf.size ()));
165
+ }
166
+ };
167
+
168
+ std::expected<int , std::error_code> sqrt (int x) {
169
+ if (x < 0 )
170
+ return std::unexpected{make_error_code (std::errc::argument_out_of_domain)};
171
+
172
+ for (int i = 0 ;; i++)
173
+ if (i * i >= x)
174
+ return i;
175
+ }
176
+
177
+ }
178
+
179
+ namespace screenshot2 {
180
+
181
+ int sqrt (int x) {
182
+ if (x < 0 ) {
183
+ errno = EDOM;
184
+ return -1 ;
185
+ }
186
+
187
+ for (int i = 0 ;; i++)
188
+ if (i * i >= x)
189
+ return i;
190
+ }
191
+
192
+ }
You can’t perform that action at this time.
0 commit comments