C++ 17 if-switch初始化

C++ 17 if-switch初始化

C++17ifswitch 增加了一个很实用的小特性:可以在条件判断前先写一段初始化语句。这样既能少写一行代码,也能把变量的作用域限制在当前判断语句里,让代码更紧凑一些。

1. 为什么这个特性好用?

C++17 之前,我们经常会这样写:

1
2
3
4
int value = someFunction();
if (value > 0) {
// do something
}

这段代码当然没问题,但有一个小缺点:valueif 语句结束以后仍然存在。
如果这个变量只是为了当前判断临时使用,那它暴露在外部作用域里就有点多余了。

C++17 允许我们把它收进 if 语句里:

1
2
3
if (int value = someFunction(); value > 0) {
// do something
}

这样写以后,value 的作用域只在这个 if / else 结构内部,更干净。

2. if 初始化语句

2.1 基本语法

1
2
3
if (init-statement; condition) {
// ...
}

其中:

  • init-statement:初始化语句
  • condition:真正的判断条件

2.2 一个最简单的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;

int someFunction()
{
return 10;
}

int main()
{
if (int value = someFunction(); value > 0) {
cout << "value > 0: " << value << endl;
} else {
cout << "value <= 0: " << value << endl;
}

return 0;
}

这里的 valueifelse 中都能使用,但出了这个语句块就不可见了。

2.3 和容器查找一起使用

这个特性在查找操作里也很常见,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <map>
#include <iostream>
using namespace std;

int main()
{
map<int, string> data{
{1, "apple"},
{2, "banana"}
};

if (auto it = data.find(2); it != data.end()) {
cout << "find: " << it->second << endl;
} else {
cout << "not found" << endl;
}

return 0;
}

这种写法非常自然,因为 it 本来就只是当前查找逻辑里的一个临时迭代器。

3. switch 初始化语句

switch 也支持同样的语法:

1
2
3
4
switch (init-statement; expression) {
case ...:
break;
}

3.1 基本示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;

int someFunction()
{
return 2;
}

int main()
{
switch (int value = someFunction(); value) {
case 1:
cout << "value is 1" << endl;
break;
case 2:
cout << "value is 2" << endl;
break;
default:
cout << "value is " << value << endl;
break;
}

return 0;
}

这里的 value 也只在这个 switch 语句内部有效。

3.2 一个更贴近业务的例子

比如函数返回状态码时,可以这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
enum State
{
Ok = 0,
Warning = 1,
Error = 2
};

State getState()
{
return Warning;
}

int main()
{
switch (auto state = getState(); state) {
case Ok:
cout << "ok" << endl;
break;
case Warning:
cout << "warning" << endl;
break;
case Error:
cout << "error" << endl;
break;
}

return 0;
}

4. 这个特性的几个优点

4.1 限制变量作用域

变量只在 ifswitch 内部有效,减少外部命名污染,这一点是最直接的好处。

4.2 代码更紧凑

变量初始化和判断逻辑放在一起,读代码时上下文更集中。

4.3 降低误用概率

有些变量如果在外部作用域还能访问,后面可能会被误用。现在它的生命周期被收紧以后,这类问题会少一些。

5. 使用时的注意点

5.1 中间是分号,不是逗号

这类写法的形式是:

1
if (初始化语句; 条件)

很多人第一次写时容易手滑。

5.2 变量只能在当前语句结构里用

下面这种写法是不行的:

1
2
3
4
5
if (int value = someFunction(); value > 0) {
cout << value << endl;
}

// cout << value << endl; // 这里已经访问不到 value 了

5.3 不要为了“新特性”而强行使用

如果初始化语句很长,或者判断条件本身已经足够复杂,把它们硬塞进一行里反而会降低可读性。
所以这个特性虽然好用,但也要看场景。

总结

ifswitch 初始化语句算不上特别大的语言升级,但它确实很实用。尤其是在查找、状态判断、临时变量判断这些场景下,用起来会让代码更整洁。
如果你已经在使用 C++17,这个写法还是很值得养成习惯的。