用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 ...
随机推荐
- jsp页面出错 Cannot call sendRedirect() after the response has been committed
sendRedirect()不能多次调用,检查下代码
- 第二阶段:4.产品功能需求文档PRD:7.案例总结
Dev就是一些开发 这就是一个评价表格 每次沟通都要记得记录以及总结反思
- Visual Studio 2019使用docker开发(vsdbg的问题)
前言 vsdbg在国内下载的速度真的很慢,借助迅雷也没办法起飞. 这里还是来探讨下如何用迅雷进行下载以后安装操作. 遇到的状况 在使用Visual Studio 2019进行开发调试(https:// ...
- 从零开始のcocos2dx生活(八)ParticleSystemQuad
https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/#_1 写的真的非常好-最近没时间拜读,只看 ...
- Lambda函数到底是个什么
1 什么是Lambda函数 lambda函数是指简单的代码片段,通常认为是不值得命名的函数,它不能重复使用,能方便程序员使用,增强代码可读性,降低代码出错概率. [ 捕获列表 ] (参数) -> ...
- 【题解】P4137 Rmq Problem(莫队)
[题解]P4137 Rmq Problem(莫队) 其实这道题根本就不用离散化! 因为显然有\(mex\)值是\(\le 2\times 10^5\)的,所以对于大于\(2\times 10^5\)的 ...
- $Noip2018/Luogu5020$ 货币系统 $dp$
$Luogu$ 去年我这题获得了$20$的好分数$ovo..........$ $Sol$ 现在来看其实非常显然叭,只要把能被别的数表示出来的数去掉就好了. $f[i]$表示$i$数能否被其他数表示. ...
- 「2018-12-02模拟赛」T3 约束排列 解题报告
3.约束排列(place.pas/cpp/in/out) 问题描述: 给出 n 个互不相同的小写字母,表示出现的字符类型,以及 k 个约束关系: .....,表示 ai 必须出现在 bi 前面(ai, ...
- Sample Code之Take a screenshot of a SceneView
周末事情太多了,以后就工作日发布随笔吧.周末的话,看心情,也许也会发~ 今天的实例代码解析是Take a screenshot of a SceneView,也就是获取快照,话不多说,进入正题. 首先 ...
- Google 开源的 Python 命令行库:fire 实现 git 命令
作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...