1 结构化绑定概述
结构化绑定允许用一个对象的元素或成员同时实例化多个实体。文字说明可能显得苍白无力。下面用代码的方式来说明:
typedef struct Data {
int i = 0;
std::string s="Hello World";
} DATA;
int main()
{
DATA stTmp;
auto [u,v]=stTmp;
std::cout<<u<<","<<v<<std::endl;
return 0;
}
看上代码第9行是不是很熟悉,像极了Python。C++17已经正式支持了这种语法并且命名为结构化绑定,
除了上面的写法外,还支持以下几种写法:
DATA data1;
auto [u1, v1] {data1};
DATA getStructData() {
return DATA{1, "hello C++"};
}
auto [u2,v2]=getStructData();
结构体绑定返回值可以进行独立操作,如:
if(u2 == 1){
std::cout<<v2<<std::endl;
}
在C++17之前,如果要处理一个结构体返回对象需要先定义一个结构体变量,然后在对结构体的值进行分别处理。有了结构化绑定之后,在实际的编程时就可以直接访问返回的结构体。从某种程度上来说,增强了代码的可读性。当然这一特性除了应用在上面的场景外,也可以用于map容器的遍历。如下面的写法:
std::map<int,std::string> m_mapDataValue;
//此处省略map赋值操作
for (const auto& [key, val] : m_mapDataValue) {
std::cout << key << ": " << val << '\n';
}
怎么样?是不是更容易理解代码,通过这种直接的方式处理,不得不说是一种进步。
2 细品结构化绑定
上面的结构化绑定技术在使用时方便了我们的操作,但是本着对待问题穷追不舍的精神,我们需要了解结构化绑定的内部处理。诚然天下没有免费的午餐,结构化绑定也是,在结构化绑定的实现过程中,里面暗藏了一个隐藏的匿名对象。而结构化绑定时指定的变量实际上就是通过这个隐藏的匿名对象进行赋值的。且看下面的代码拆解:
auto [u1, v1] {data1};
如上面的代码,在实际的运行中实际上等同于下面的这段代码:
auto e = data1;
u1 = e.i;
v1= e.s;
上面的代码说明,u1, v1是e对象的一份本地拷贝,是e.i和e.s的别名。值得注意的是,他们并不是引用的关系,如果在结构化绑定之后重新对data1进行赋值,u1和v1的值是不是随之改变的。如下面代码所示:
typedef struct Data {
int i = 0;
std::string s="Hello World";
} DATA;
int main()
{
DATA stTmp;
auto [u,v]=stTmp;
std::cout<<u<<","<<v<<std::endl;
stTmp.i=3;
stTmp.s="哈,来模仿我呀";
std::cout<<"修改数据之后[u,v]和stTmp值的变化:"<<std::endl;
std::cout<<u<<","<<v<<std::endl;
std::cout<<stTmp.i<<","<<stTmp.s<<std::endl;
return 0;
}
上面代码的运行结果如下:
0,Hello World
修改数据之后[u,v]和stTmp值的变化:
0,Hello World
3,哈,来模仿我呀
运行结果也证明了上述的结论:结构化绑定只是对结构体对象的值进行拷贝,而不是引用关系。
3 哪些场景可以使用结构体绑定
原则上讲,结构化绑定适用于所有只有 public 数据成员的结构体、 C 风格数组和类似元组 (tuplelike)的对象。结构化绑定中声明的变量也必须和结构体成员的数量一致。当然,在声明结构体变量时可以使用“_”,但是在同一段代码中不能使用重复的变量,如下面的代码中编译时是会报错的。
auto [_,v]=stTmp;//可以正常编译
auto [_,v1]=stTmp;//编译时会报错
下面,将对具体的使用场景进行详细说明。
3.1 结构体和类
在前面的介绍中,使用结构化绑定时都是一些正常的场景,但是在实际编程时,结构体会使用继承。因此,在这种情况下需要遵循特定的使用原则:所有的成员变量需要在子类或者父类中统一声明。不能出现父类和子类都有定义的情况。如下代码所示:
struct Base {
int i = 0;
std::string s="Hello World";
};
struct Data1:public Base{
};
struct Data2:public Base{
int c=99;
};
int main()
{
auto [u,v]{Data1()};//可以编译通过
auto [u1,v1,k]{Data2()}//编译报错
return 0;
}
如上,代码编译报错的信息为:
3.2 原生数组
对原生数组使用结构化绑定时需要注意的是只有在数组的长度一定的情况下才能使用结构化绑定,且声明的对象个数要和数组长度保持一致。数组作为按值传入的参数时是不能使用结构化绑定的,这个时候数组会退化为相应的指针。如下面的代码:
int arr[] = { 47, 11 };
auto [x, y] = arr; // 正常通过
auto [z] = arr; // 编译报错,声明对象和数组长度不一致
还有一点需要注意的是,C++可以通过引用返回具有大小信息的数组,且是可以使用结构化绑定的,如:
auto getArray()->int(&)[2];
auto [u,v] = getArray();
3.3 std::pair, std::tuple 和 std::array 结构化绑定是可拓展的,可以为任何类型添加结构化绑定的支持。在C++标准库中添加了 std::pair<>、std::tuple<>、 std::array<> 的结构化绑定支持。
可以使用getArray()返回数组元素,如:
std::array<int, 4> getArray();
auto [a, b, c, d] = getArray();
在使用非临时变量的 non-const 引用进行绑定时,还能够对返回的数组元素进行修改:
std::array<int, 4> stdArr { 1, 2, 3, 4 };
auto& [a, b, c, d] = stdArr ;
a+=10;//编译正常
const auto & [e, f, g, h] = stdArr;
e+=10;//编译报错。e为常量引用
auto&& [i, j, k, l] = stdarr;
i += 10;//编译正常
同数组一样,可以通过声明相同数量的对象返回tuple中的元素。如下代码所示:
int main()
{
std::tuple<int,std::string,float> myTuple(1,"Hello World",2.0);
auto [a,b,c] = myTuple;
std::cout<<a<<","<<b<<","<<c<<std::endl;
return 0;
}
代码运行结果如下图所示:
std::pair在map值插入方法中用的比较多,通过结构化绑定可以直接对值进行操作,提高了代码的可读性。在if语句的初始化语句中有过介绍。大家可以跳转到这里:[C++17常用新特性(一)---带初始化的 if 和 switch 语句]
4 总结
在C++标准库中只对一些类型提供了结构化定义的支持,在使用时也可以自己编写自定义类型的结构化接口。具体使用根据实际编程时具体需要而定。不得不说的是结构化绑定确实帮助我们可以直接操作结构体定义的变量,提升了代码的可读性,但是从某方面说这一操作又有很多的局限性,如结构化绑定时声明的对象必须和绑定对象数量一致、对类的绑定时要求非静态成员变量必须统一在父类或者子类中进行定义等,这些要求在实际编程时带来的限制相比较而言并不是非得结构化绑定不可。因此大家在使用时需要根据实际情况,是不是为了代码可读性而牺牲掉原有的一些东西。欢迎大家留言讨论。谢谢!
- EOF -
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/W1bYA1vJCa-5N-Q-yWwjCg
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。