1. 简介
绑定特殊名称到初始化器的子对象或元素。
类似引用,一个结构化绑定是一个已存在对象的一个别名; 但 一个结构化绑定 不属于 引用类型。
2. 语法
attr(optional) cv-auto ref-qualifier(optional) [ identifier-list ] = expression; (1)
attr(optional) cv-auto ref-qualifier(optional) [ identifier-list ] { expression }; (2)
attr(optional) cv-auto ref-qualifier(optional) [ identifier-list ] ( expression ); (3)
attr, 任意数量属性的序列
cv-auto, 包含cv限定的类型说明符 auto 或 同时包含 存储类说明符 static / thread_local
ref-qualifier, 引用说明符: & 或 &&
identifier-list,以逗号分隔的标识符列表
expression, 顶层没有逗号运算符的表达式(从语法上讲,是赋值表达式),并且它具有数组或非联合类类型。
注: 如果表达式引用 identifier-list(标识符列表)中的任何名称,则声明格式错误。
3. 说明
结构化绑定声明将标识符列表中的所有标识符作为 声明所在作用域 中的名称引入,并将它们绑定到由表达式表示的对象的子对象或元素。
结构化绑定声明, 首先引入一个唯一命名的变量(此处用 e 表示)来保存初始值设定项的值,如下:
a. 如果 expression 具有数组类型 A 并且不存在引用限定符,则 e 具有类型 cv A,其中 cv 是 cv-auto 序列中的 cv 限定符;那么 e 的每个元素都将 被拷贝初始化(对于应 声明形式(1)) 或从表达式的相应元素直接初始化(对应 声明形式((2),(3))
b. 否则 e 将以 把声明中的 [ identifier-list ] 替换为e后相同的形式 被定义,比如:
attr(optional) cv-auto ref-qualifier(optional) [ identifier-list ] = expression; 将等价于 attr(optional) cv-auto ref-qualifier(optional) e = expression;
我们使用 E类型 来表征 e 解引用后的类型(即 E = std::remove_reference_t<decltype((e))>);
然后,结构化绑定声明以三种可能的方式之一执行绑定,具体取决于 E:
a. 如果 E 是一个数组类型,那么[ identifier-list ]中的标识符将逐一地被绑定到 数组的元素;
i. [ identifier-list ]中的每个标识符成为指向数组相应元素的左值的名称;
ii. [ identifier-list ]中的标识符数目 必须 与 数组元素的数目 一致;
iii. 每个标识符的引用类型即为对应的数组元素类型。 请注意,如果数组类型 E 具有 cv 属性,那么它的元素类型也具有 cv 属性的。
1 int main() 2 { 3 int a[2] = { 1, 2 }; 4 5 auto [x, y] = a; // creates e[2], copies a into e, 6 // then x refers to e[0], y refers to e[1] 7 8 // 修改 x与y的值,不影响 a 数组 9 x = 10; 10 y = 20; 11 12 auto& [xr, yr] = a; // xr refers to a[0], yr refers to a[1] 13 14 // 修改 xr与yr的值, a 数组也会跟着变更 15 xr = 3; 16 yr = 4; 17 18 // decltype(xr)得到的类型为int, 所以修改 dxr的值,不会影响 xr的值,更不会影响到 a[0]的值 19 decltype(xr) dxr = xr; 20 dxr = 11; 21 22 return 1; 23 }
b. 如果 E 是非联合体类型并且 std::tuple_size<E> 是具有成员命名 value 的完整类型(不管该 value成员的类型或访问权限是什么 ),那么将使用 “类元组” 的绑定协议;
i. 表达式 std::tuple_size<E>::value 必须为 格式正确的 整型常量表示式,且 [ identifier-list ]中的标识符数目必须与std::tuple_size<E>::value 的值一致;
ii.对于 [ identifier-list ]中的每个标识符,都会引入一个变量,这个变量的类型为 std::tuple_element<i, E>::type 类型的引用类型: 当它对应的初始化器为一个左值时,为 左值引用; 否则,为右值引用
c. 如果 E 是非联合体类型 但 std::tuple_size<E>不是一个完整类型,那么 [ identifier-list ]中的标识符将逐一地被绑定到 E 的可访问数据成员

浙公网安备 33010602011771号