C++17 if/switch语句初始化

Share on:
400 Words | Read in about 2 Min | View times

Overview

C++17引入了if/switch语句初始化的新特性,既解决了变量命名问题,也可使声明变量的作用域缩小。这一新特性还可以作用于结构化绑定。本节内容主要介绍if/switch语句初始化的使用。

本系列文章将包括以下领域:

本章其他内容请见 《现代C++》

什么是if/switch语句初始化

在C++17之前,一段if-else段落或switch段落的基本形式都是如下这种形式:

 1variable-init-statement //if中使用的变量的初始化语句
 2if (condition) { //对前面声明的变量进行判断
 3    //...
 4} else {
 5    //...
 6}
 7
 8variable-init-statement //switch中使用的变量的初始化语句
 9switch (condition) {
10default:
11    break;
12}

可以看出,两处初始化语句必须使用不同的变量名,可能导致变量命名词穷,尤其在获取迭代器的代码中比较显著。

另外两处初始化语句将处于一个单独的作用域,即暴露在ifswitch所在的作用域之外。当然也可以这样书写,但还是不方便:

 1{
 2    variable-init-statement
 3    if (condition) {
 4        //...
 5    } else {
 6        //...
 7    }
 8}
 9
10{
11    variable-init-statement
12    switch (condition) {
13    default:
14        break;
15    }
16}

从C++17开始,可以通过如下的语法解决了上述问题:

 1if (init; condition) {
 2    //...
 3} else {
 4    //...
 5}
 6
 7switch(init; condition) {
 8default:
 9    break;
10}

命名困难

我们前面提到if/switch语句初始化可以解决命名困难,常见的场景是获取STL容器的迭代器时:

 1int main() {
 2    std::map<std::string, int> mp {
 3        {"hello", 0}, {"zhxilin", 1}
 4    };
 5
 6    //C++17之前
 7    auto itr = mp.find("hello");
 8    if (itr != mp.end())
 9        std::cout << itr->first << ", " << itr->second << std::endl;
10
11    auto itr2 = mp.find("zhxilin");
12    if (itr2 != mp.end())
13        std::cout << itr2->first << ", " << itr2->second << std::endl;
14
15    return 0;
16}

作用域逃逸

传统的写法初始化声明的语句的作用域要比if-elseswitch的作用域要大,不利于管理:

 1int main() {
 2    std::map<std::string, int> mp {
 3        {"hello", 0}, {"zhxilin", 1}
 4    };
 5
 6    //C++17之前解决作用域逃逸的方式,顺带解决了命名困难的问题
 7    {
 8        auto itr = mp.find("hello");
 9        if (itr != mp.end())
10            std::cout << itr->first << ", " << itr->second << std::endl;
11    }
12
13    {
14        auto itr = mp.find("zhxilin");
15        if (itr != mp.end())
16            std::cout << itr->first << ", " << itr->second << std::endl;
17    }
18
19    return 0;
20}

if/switch语句初始化

因此,C++17提供的if/switch语句初始化语法糖,可以一举解决上面两个问题,并使代码更加精炼:

 1int main() {
 2    std::map<std::string, int> mp {
 3        {"hello", 0}, {"zhxilin", 1}
 4    };
 5
 6    //C++17
 7    if (const auto itr = mp.find("hello"); itr != mp.end())
 8        std::cout << itr->first << ", " << itr->second << std::endl;
 9
10    if (const auto itr = mp.find("zhxilin"); itr != mp.end())
11        std::cout << itr->first << ", " << itr->second << std::endl;
12
13    return 0;
14}

既限定了作用域,也可以在各自的作用域内使用相同的变量名。

与结构化绑定结合

if/switch语句初始化还可以在结构化绑定中使用:

1int main() {
2    std::map<std::string, int> mp;
3
4    if (auto [itr, inserted] = mp.insert({"zhxilin", 1}); inserted)
5        std::cout << itr->first << ", " << itr->second << std::endl;
6
7    return 0;
8}

可以设想一下,C++17之前这段代码需要更长的代码才能完成。

以上,就是C++17的新特性——if/switch语句初始化。

Prev Post: 『C++17结构化绑定』
Next Post: 『C++17折叠表达式』