距离C++17发布已经半年有余,由于编译环境的问题一直无法体验到C++17的编程乐趣,趁着Mac系统更新,抢先体验一下C++17的强大之处。
1. 关联式容器遍历新方式
C++中关联式容器一般是指如map,set等类型,此处以map为例,下面是一段C++17(11)的map的声名及初始化,下面我们来对比对dict的遍历方式的区别。
map<int, bool> dict = {{1, 2}, {2, 3}};
C++11/14遍历方式
// 兼容C++98
for (auto it = dict.cbegin(); it != dict.cend(); ++it)
{
cout << it->first << " " << it->second << endl;
}
//C++11及C++14
for (auto &it : dict)
{
cout << it.first << " " << it.second << endl;
}
C++17新引入的遍历方式
for (auto &[k, v] : dict)
{
cout << k << ' ' << v << endl;
}
完整代码块
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<int, bool> dict = {{1, 2}, {2, 3}};
// 旧方式
for (auto it = dict.cbegin(); it != dict.cend(); ++it)
{
cout << it->first << " " << it->second << endl;
}
// C++11/14
for (auto &it : dict)
{
cout << it.first << " " << it.second << endl;
}
// C++17
for (auto &[k, v] : dict)
{
cout << k << ' ' << v << endl;
}
return 0;
}
1. if/switch块的变量初始化
考虑一个使用场景,对前面声明的dict,如果dict是否包含key=2,如果有将其value值输入。
传统写法(C++11之后)
auto it = dict.find(2);
if (it != dict.end())
{
cout << "Nice: " << it->second << endl;
}
上面的写法乍看起来没有什么总是,中规中距同时兼顾了性能问题,但代码看起来不够优雅,并且it变量被声名之后在相应的代码块作用域内一直有效。有没有办法更优雅一点呢,如果不想让it生存太久,或许下面的方式是可以的:
if (dict.find(2) != dict.end())
{
cout << "Nice: " << dict[2] << endl;
}
上面的代码成功消失了it变量,但与此同时让代码性能下降了,多了一次map的查询操作。然而步入C++17之后,让事情变得更简单了,可以如此优雅的写代码了,看下面>>
if(auto it = dict.find(2); it != dict.end())
{
cout << "Nice2: " << it->second << endl;
}
else
{
cout << "Fail: " << (it == dict.end()) << endl;
}
上面的写法让it的生命周期存在于if…else…的代码块作用域内,代码块前后还可以继续使用it来定义其它类型的变量。同理switch也支持这种用法,不再一一列举;
C++17的更新可以大大提交C++的编码及阅读效率,并且使得C++这门古老的语言更加现代化,人性化。