现代C++编程实战:132个核心技巧示例(原书第2版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.13.3 工作原理

结构化绑定是一种语言特性,它的工作原理与std::tie()类似,只不过我们不必为每个需要用std::tie()显式解包的值定义命名变量。在结构化绑定中,我们使用auto标识符在单个定义中定义所有命名变量,以便编译器可以推断每个变量的正确类型。

为了举例说明这一点,我们考虑向std::map中插入项的情况。insert方法返回一个std::pair,其中包含已插入元素或阻止插入的元素的迭代器,以及一个指示插入是否成功的布尔值。下面所示的代码非常明确,但是使用second或first->second使代码很难阅读,因为你需要不断地弄清楚它们代表什么:

使用std::tie可以使上述代码更具可读性,它将元组解包为单个对象(并与std::pair一起使用,因为std::tuple有一个来自std::pair的转换赋值):

代码并不一定更简单,因为它需要提前定义解包到的对象。类似地,元组的元素越多,需要定义的对象就越多,但是使用命名对象使代码更容易阅读。

C++17的结构化绑定将元组元素解包到命名对象中,该特性非常重要。它不需要使用std::tie(),并且对象在声明时被初始化:

在前面的例子中,使用多个块是必要的,因为变量不能在同一个块中重新声明,结构化绑定意味着使用auto标识符进行声明。因此,如果需要像前面的示例那样进行多个调用,并使用结构化绑定,则必须使用不同的变量名或多个块。另一种选择是不使用结构化绑定并使用std::tie(),因为它可以用相同的变量调用多次,所以只需要声明它们一次。

在C++17中,也可以在if和switch语句中以if(init; condition)和switch(init;condition)这种形式声明变量。这可以与结构化绑定结合,以生成更简单的代码。让我们看一个例子:

在前面的代码片段中,我们尝试向map中插入一个新值,结果被解包到两个变量:it和inserted,它们在初始化部分的if语句的作用域中定义。我们根据inserted变量的值计算if语句的条件。