网站首页 > 技术文章 正文
提案
C++17 功能特性 | 提案 | GCC | Clang | MSVC |
结构化绑定 | P0217R3 | 7 | 4 | 19.11* |
结构化绑定由 Herb Sutter、Bjarne Stroustrup、Gabriel Dos Reis 在 https://wg21.link/p0144r0中首次提出, 当时提议使用花括号而不是方括号。
最终被接受的是 Jens Maurer 发表于https://wg21.link/p0217r3的提案。
语法
- 属性(可选) cv-auto 引用运算符(可选) [ 标识符列表 ] = 表达式 ;
- 属性(可选) cv-auto 引用运算符(可选) [ 标识符列表 ] { 表达式 } ;
- 属性(可选) cv-auto 引用运算符(可选) [ 标识符列表 ] ( 表达式 ) ;
属性 | 任意数量的属性的序列 |
cv-auto | 可有 cv 限定的 auto 类型说明符,也可以包含存储类说明符 static 或 thread_local ;在 cv 限定符中包含 volatile 是被弃用的 (C++20 起) |
引用运算符 | & 或 && 之一 |
标识符列表 | 此声明所引入的各标识符的逗号分隔的列表 |
表达式 |
对于一个 类型 type这套 API 需要如下的组件:
|
- 结构化绑定其实有一个隐藏的匿名对象。结构化绑定时引入的新变量名其实都指向这个匿名对象的成员或元素
auto [u, v] = ms;
//相当于
auto e = ms;
aliasname u = e.i;
aliasname v = e.s;
//u和 v仅仅是 ms的一份本地拷贝的成员的别名
// u和 v并不是 e.i和 e.s的引用(而是它们的别名)
- 说明符会作用在匿名实体e上,而不是结构化绑定引入的新的变量名上
alignas(16) auto [u, v] = ms; // 对 齐 匿 名 实 体e, 而 不 是u、v
- e的生命周期和结构化绑定(方括号中的)的生命周期相同,当结构化绑定离开作用域时 e也会被自动销毁
- 如果一个结构化绑定是引用类型,而且是对一个临时对象的引用,那么和往常一样,临时对象的生命周期会被延长到结构化绑定的生命周期
MyStruct getStruct();
...
const auto& [a, b] = getStruct();
std::cout << "a: " << a << '\n'; // OK
- 使使用了 auto结构化绑定也不会发生类型退化 (decay是指当参数按值传递时发生的类型转换,例如原生数组会转换为指针,顶层修饰符例如 const和引用会被忽略)
struct S {
const char x[6];
const char y[3];
};
S s1{};
auto [a, b] = s1; // a类型是char [6],b类型是char [3]
- 结构化绑定中声明的变量名的数量都必须和元素或数据成员的数量相同
- 目前还不支持嵌套化的结构化绑定、联合使用结构化绑定
例子
#include <iostream>
#include <vector>
#include <tuple>
void test_array()
{
int a[2] = {1,2};
auto [x,y] = a; // 创建 e[2],复制 a 到 e,然后 x 指代 e[0],y 指代 e[1]
auto& [xr, yr] = a; // xr 指代 a[0],yr 指代 a[1]
std::cout << x << y << std::endl;
}
void test_tuple()
{
float x{};
char y{};
int z{};
std::tuple<float&,char&&,int> tpl(x,std::move(y),z);
const auto& [a,b,c] = tpl;
// a 指名指代 x 的结构化绑定;decltype(a) 为 float&
// b 指名指代 y 的结构化绑定;decltype(b) 为 char&&
// c 指名指代 tpl 的第 3 元素的结构化绑定;decltype(c) 为 const int
std::cout << a << b << c << std::endl;
}
void test_class()
{
struct MyStruct {
int i = 0;
std::string s;
};
MyStruct ms;
auto [u, v] = ms;
auto [u2, v2] {ms};
auto [u3, v3] (ms);
std::cout << u << v << std::endl;
}
int main(int argc, char** argv) {
test_array();
test_tuple();
test_class();
return 0;
}
https://wandbox.org/
惯用法
函数返回值,同时返回多个值
std::tuple<char, float, std::string> getTuple();
...
auto [a, b, c] = getTuple(); // a,b,c的 类 型 和 值 与 返 回 的tuple中 相 应 的 成 员 相 同
std::map<std::string, int> coll;
auto [pos, ok] = coll.insert({"new", 42});
if (!ok) {
// 如 果 插 入 失 败, 用pos处 理 错 误
}
扩展
为结构化绑定提供 Tuple- Like API
- 上一篇: C语言中main函数详解
- 下一篇: C语言100题集合027-二维数组的经典案例,非常重要
猜你喜欢
- 2025-01-08 嵌入式中,日志调试法的一些规则!
- 2025-01-08 一行代码改进:Logtail的多行日志采集性能提升7倍的奥秘
- 2025-01-08 嵌入式大杂烩周记 第 7 期:zlog
- 2025-01-08 C语言总结:C语言字符串练习题(十二种习题示例)
- 2025-01-08 C语言100题集合027-二维数组的经典案例,非常重要
- 2025-01-08 一个例子让你看清线程调度的随机性
- 2025-01-08 C语言中main函数详解
- 2025-01-08 64TB硬盘容量测试程序(C++)
- 2025-01-08 使用CyberRT写第一个代码
- 2025-01-08 计算机启动知识系列 - 一个UEFI例子
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)