用set、map等存储自定义结构体时容器内部判别各元素是否相同的注意事项
STL作为通用模板极大地方便了C++使用者的编程,因为它可以存储任意数据类型的元素
如果我们想用set与map来存储自定义结构体时,如下
struct pp
{
double xx;
double yy;
};
set<pp> aa[]; struct ab
{
double aa;
double bb;
double cc;
}stra[];
map<ab, int> mm;
上面我们使用 set 来存储 pp结构体,将 ab结构体作为一个映射的Key
显然我们这样做编译器会报错,原因是set与map内部需要比较各个元素的大小,这样我们的结构体缺失了小于号的重载,无法存储
改后如下:
struct pp
{
double xx;
double yy;
bool operator < (const pp a)const //重载小于号
{
return xx < a.xx;
}
};
set<pp> st; struct ab
{
double aa;
double bb;
double cc;
bool operator < (const ab a)const //重载小于号
{
return aa < a.aa;
}
};
map<ab, int> mp;
这样用通过结构体中的某个数比较来定义结构体的小于号,我们的程序就编译成功了
但在运行时我们就会发现一个现象,那就是如果我们
将一个pp结构体
A(A.xx == 1, A.yy == 2)
插入集合st之后
我们若再插入一个pp结构体
B(B.xx == 1,B.yy == 3)
后面检查时会发现,集合中只有A而没有B,但插入insert操作是确实执行过的
那么原因应该只有一个,就是set内部将A与B视为同一个元素,由于set的去重性,第二次加入B不成功。
为何会认为A,B相同?注意到我们的小于号重载
bool operator < (const pp a)const //重载小于号
{
return xx < a.xx;
}
要知道上面我们仅仅用pp结构体成员xx来定义小于号,所以由于A,B的xx相同(都是1),set内部认为A,B相同(即使A,B的yy值不相同)
类似地,我们如果给map里面加上两对 “键-值”
而这两个键(都是ab结构体)的成员aa相同而bb与cc不相同的话
我们的mp映射里面也会只有一对“键-值”,(而且值是后一个加入的值覆盖掉了前面的值)
解决方法就是修改小于号重载函数,使得结构体成员有一个不相同时,return后面的表达式就不能相等
举例如下
struct pp
{
double xx;
double yy;
bool operator < (const pp a)const
{
return xx * yy - xx / yy + yy / 2.745 < a.xx * a.yy - a.xx / a.yy + a.yy / 2.745; //用于集合的必备操作
}
};
set<pp> aa[]; struct ab
{
double aa;
double bb;
double cc;
bool operator < (const ab a)const
{
return aa * cc / 5.123 + bb / 3.145 - aa < a.aa * a.cc / 5.123 + a.bb / 3.145 - a.aa;//用于映射的必备操作
}
}
map<ab, int> mm;
可看出,新的重载方式囊括了结构体内部的所有成员,并且使用了三位小数,确保了只有在两个结构体内部成员完全一样时容器内部才会判为相同元素,出现错误的概率被降到极低。
所以可以在表面现象上确定的是,set与map内部不仅用小于号来判断元素大小,而且也用它来判断元素是否相同
保证重载小于号的返回表达式的比较值对于不同元素具有真正的辨别性,是用这些容器来装载自定义结构体所需要注意的事项
用set、map等存储自定义结构体时容器内部判别各元素是否相同的注意事项的更多相关文章
- Solidity的自定义结构体深入详解
一.结构体定义 结构体,Solidity中的自定义类型.我们可以使用Solidity的关键字struct来进行自定义.结构体内可以包含字符串,整型等基本数据类型,以及数组,映射,结构体等复杂类型.数组 ...
- gin中绑定表单数据至自定义结构体
package main import "github.com/gin-gonic/gin" type StructA struct { FieldA string `form:& ...
- typedef和自定义结构体类型
在自定义结构体类型时会用到typedef关键字.大家都知道typedef是取别名的意思,在C语言中跟它容易混淆的有const,#define等,其区别不在本篇文章讨论之列. /*定义单链表结点类型*/ ...
- qsettings 保存自定义结构体(QVariant与自定义结构体相互转化)
参考博文:QVariant与自定义数据类型转换的方法. 这里摘取其关键内容: 1.将自定义数据类型使用Q_DECLARE_METATYPE宏进行声明,便于编译器识别. 2.在插入对象的时候,声明QVa ...
- iOS自定义结构体
一.提要 通过以官方的CGSize为例,自定义Objective-C中的结构体,并使用. 二.CGSize 1.系统定义的CGSize结构体 struct CGSize { CGFloat width ...
- Qt--信号槽传递自定义结构体参数
自定义结构体参数的信号槽连接 (1) 对于自定义的结构体参数,信号槽无法识别参数,导致信号槽连接不起作用.所以需要注册结构体参数.在结构体中声明结束的地方加上结构体注册. struct DealDet ...
- 使用类/结构体时关于ZeroMomery用法错误
今天同事在写了如下结构体: typedef struct _tagInfo { std::list<int> lst; std::vector<int> nVec; } INF ...
- QT:用QSet储存自定义结构体的问题——QSet和STL的set是有本质区别的,QSet是基于哈希算法的,要求提供自定义==和qHash函数
前几天要用QSet作为储存一个自定义的结构体(就像下面这个程序一样),结果死活不成功... 后来还跑到论坛上问人了,丢脸丢大了... 事先说明:以下这个例子是错误的 #include <QtCo ...
- 再谈:自定义结构体的对齐问题之__attribute__ ((packed))方法【转】
转自:https://blog.csdn.net/ipromiseu/article/details/5955295 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.c ...
随机推荐
- lambda应用
def test(a, b, func): result = func(a, b) print(result) test(10, 15, lambda x, y: x + y) #coding=utf ...
- Java 8 访问接口的默认方法
Java 8 API提供了很多全新的函数式接口来让工作更加方便,有一些接口是来自Google Guava库里的,即便你对这些很熟悉了,还是有必要看看这些是如何扩展到lambda上使用的. 一.Opti ...
- 深入CAS的底层实现机制,以及对应的使用风险
概述 CAS(Compare-and-Swap),即比较并替换,是一种实现并发算法时常用到的技术,Java并发包中的很多类都使用了CAS技术.CAS也是现在面试经常问的问题,本文将深入的介绍CAS的原 ...
- 「洛谷P1231」教辅的组成 解题报告
P1231 教辅的组成 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习 ...
- 7.netty内存管理-ByteBuf
ByteBuf ByteBuf是什么 ByteBuf重要API read.write.set.skipBytes mark和reset duplicate.slice.copy retain.rele ...
- javascript-void keyword
javascript-void keyword 写在前面 ECMA-262定义了ECMAScript所支持的关键字(keyword),关键字不能用作ECMAScript程序的标识符(Indetifie ...
- 25.xlrd、xlwt和openpyxl模块的比较和使用
xlrd.xlwt和openpyxl模块的比较:1)xlrd:对xls.xlsx.xlsm文件进行读操作–读操作效率较高,推荐2)xlwt:对xls文件进行写操作–写操作效率较高,但是不能执行xlsx ...
- 【tf.keras】AdamW: Adam with Weight decay
论文 Decoupled Weight Decay Regularization 中提到,Adam 在使用时,L2 与 weight decay 并不等价,并提出了 AdamW,在神经网络需要正则项时 ...
- Java和PHP加解密
PHP代码 <?php //DES加解密工具 class DesEncrypt { var $key; var $iv; function DesEncrypt($key, $iv=0) { $ ...
- hdfs/hbase 程序利用Kerberos认证超过ticket_lifetime期限后异常
问题描述 业务需要一个长期运行的程序,将上传的文件存放至HDFS,程序启动后,刚开始一切正常,执行一段时间(一般是一天,有的现场是三天),就会出现认证错误,用的JDK是1.8,hadoop-clien ...