C++17新语法之if和switch语句中可以初始化变量啦

前言

今天在看一些c++代码时偶然间发现一些示例,在if语句的小括号内居然出现了分号,难道这一段是伪代码吗?之前从来没见过这种写法,然后写了一个例子,用最新的编译器编译后发现真的是正常的代码,并且可以成功运行,然后脑袋有个声音一闪而过,是不是一直就支持这种写法,只是我不知道而已,后来几经周折,终于发现真相,原来这其实是C++17新的语法。

if 语句本来的样子

C++17之前 if 语句的小括号内只能放判断逻辑,if (condition) { /* ... */ } 也就是这样,所以如果想使用一个变量进行判断,那么这个变量必须在if语句之前进行定义,比如我们常常使用的查找map元素的逻辑:

1
2
3
4
5
6
7
{
auto it = mp.find("key");
if (it != mp.end())
return it->second;
else
return defaultValue;
}

if 语句新能力

从C++17开始,if 语句的小括号之中也可以初始化变量了,语法为 if (initializer; condition) { /* ... */ },这样做的好处就是可以更加精细的控制变量的作用域,使代码看起来更加紧凑,比如上面的例子可以改写为:

1
2
3
4
5
6
{
if (auto it = mp.find("key"); it != mp.end())
return it->second;
else
return defaultValue;
}

最直观的感受就是少了一行代码,但是更重要的特点还是他把变量 it 的作用域限制在了 if 语句之内。

另外就是能一定程度上解决代码缩进层数太多的问题,这也是实际开发过程中遇到的问题,比如下面这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
auto it = mp.find("key");
if (it != mp.end())
return it->second;
else
{
int cfg = GetConfig();
if (cfg)
return defaultValue1;
else
return defaultValue2;
}
}

在C++17之前的代码中,因为 if 语句中不能包含初始化变量的逻辑,所以会造成 if 嵌套层层递进,当这种条件太多时,缩进层数太多导致代码可读性变差,使用C++17的语法再改进一下就变成了下面这样,逻辑更加清晰了:

1
2
3
4
5
6
7
8
{
if (auto it = mp.find("key"); it != mp.end())
return it->second;
else if (int cfg = GetConfig(); cfg)
return defaultValue1;
else
return defaultValue2;
}

switch 语句也是相同的能力扩展,就不再展开说了,这里贴一个 cppreference - switch 上的例子:

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
{
struct Device
{
enum State { SLEEP, READY, BAD };
auto state() const { return m_state; }

/*...*/

private:
State m_state{};
};

switch (auto dev = Device{}; dev.state())
{
case Device::SLEEP:
/*...*/
break;
case Device::READY:
/*...*/
break;
case Device::BAD:
/*...*/
break;
}
}

似曾相识在go中

这个在if中既初始化又进行判断的语法,之前在go中也用过,类似的需求在go中的写法是:

1
2
3
4
5
6
7
func xxx() {
if value := mp["key"]; value != nil {
return value
} else {
return defaultValue
}
}

是不是很像?其实在golang中更规范的用法是使用map查找的第二个返回值来判断元素是否存在,就像下面这样:

1
2
3
4
5
6
7
func xxx() {
if value, ok := mp["key"]; ok {
return value
} else {
return defaultValue
}
}

关于语言的思考

看到上面这种golang和c++17的对比,会发现语言之间都在相互促进,这些所谓的高级语言,总能在其中一种语言中发现另一种语言的影子,也就是说在某些方面上他们是“趋同”的,可能在不久的将来会出现一种“超高级语言”,类似于C++模板机制,C++GolangPython 这些语言作为一种类型,传递到超高级语言之中,编写或者描述完功能逻辑后,自动生成对应语言的代码:

1
2
3
4
5
SuperLanguageTemplate<C++/Golang/Python>
[AutoGenerateByFollowingDescription]
{
/ * ... * /
}

总结

  • ifswitch 语句都可以在逻辑判断前初始化变量,变量的定义域可以更精细的控制
  • 编程语言之间相互“借鉴”,部分语法长得越来越像,最后不知道会不会归于统一

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

人生并不是不断失去,反过来看,其实人生应该是不断拥有,1秒,2秒,3秒,这些本就不一定属于你的时间,作为馈赠出现在了你的生命里~

2022-6-19 01:44:55

Albert Shi wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客