C++17新语法之if和switch语句中可以初始化变量啦
文章目录
- 前言
- if 语句本来的样子
- if 语句新能力
- 似曾相识在go中
- 关于语言的思考
- 总结
前言
今天在看一些c++代码时偶然间发现一些示例,在if语句的小括号内居然出现了分号,难道这一段是伪代码吗?之前从来没见过这种写法,然后用写了一个例子,用最新的编译器编译后发现真的是正常的代码,并且可以成功运行,然后脑袋有个声音一闪而过,是不是一直就支持这种写法,只是我不知道而已,后来几经周折,终于发现真相,原来这其实是C++17新的语法。
if 语句本来的样子
C++17之前 if
语句的小括号内只能放判断逻辑,if (condition) { /* ... */ }
也就是这样,所以如果想使用一个变量进行判断,那么这个变量必须在if语句之前进行定义,比如我们常常使用的查找map元素的逻辑:
{
auto it = mp.find("key");
if (it != mp.end())
return it->second;
else
return defaultValue;
}
if 语句新能力
从C++17开始,if
语句的小括号之中也可以初始化变量了,语法为 if (initializer; condition) { /* ... */ }
,这样做的好处就是可以更加精细的控制变量的作用域,使代码看起来更加紧凑,比如上面的例子可以改写为:
{
if (auto it = mp.find("key"); it != mp.end())
return it->second;
else
return defaultValue;
}
最直观的感受就是少了一行代码,但是更重要的特点还是他把变量 it
的作用域限制在了 if
语句之内。
另外就是能一定程度上解决代码缩进层数太多的问题,这也是实际开发过程中遇到的问题,比如下面这段代码:
{
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的语法再改进一下就变成了下面这样,逻辑更加清晰了:
{
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 上的例子:
{
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中的写法是:
func xxx() {
if value := mp["key"]; value != nil {
return value
} else {
return defaultValue
}
}
是不是很像?其实在golang中更规范的用法是使用map查找的第二个返回值来判断元素是否存在,就像下面这样:
func xxx() {
if value, ok := mp["key"]; ok {
return value
} else {
return defaultValue
}
}
关于语言的思考
看到上面这种golang和c++17的对比,会发现语言之间都在相互促进,这些所谓的高级语言,总能在其中一种语言中发现另一种语言的影子,也就是说在某些方面上他们是“趋同”的,可能在不久的将来会出现一种“超高级语言”,类似于C++模板机制,C++
、Golang
、Python
这些语言作为一种类型,传递到超高级语言之中,编写或者描述完功能逻辑后,自动生成对应语言的代码:
SuperLanguageTemplate<C++/Golang/Python>
[AutoGenerateByFollowingDescription]
{
/ * ... * /
}
总结
if
和switch
语句都可以在逻辑判断前初始化变量,变量的定义域可以更精细的控制- 编程语言之间相互“借鉴”,部分语法长得越来越像,最后不知道会不会归于统一
人生并不是不断失去,反过来看,其实人生应该是不断拥有,1秒,2秒,3秒,这些本就不一定属于你的时间,作为馈赠出现在了你的生命里~