C++中以自定义Particle类为key的std::map出现异常行为如何解决?
核心问题原因
std::map是有序关联容器,依赖键类型的<运算符实现严格弱序规则来区分不同的键,你当前Particle类的operator<实现不符合要求:
// 错误实现:只有三个坐标全部小于才返回true bool operator<(const Particle& rhs )const{ return (this->loc[0] < rhs.loc[0] && this->loc[1]<rhs.loc[1] && this->loc[2]<rhs.loc[2]); };
std::map会通过a < b和b < a同时为false来判定两个键相等,按上述实现,几乎所有不同坐标的粒子都会被判定为同一个键:比如坐标(0,0,0)和(1,0,0),(0,0,0) < (1,0,0)因为y坐标相等返回false,(1,0,0) < (0,0,0)因为x坐标更大返回false,所以map会认为二者是同一个键,后续插入的键会覆盖之前的值,最终conn中只会保留最后一次插入的键值对,也就是对应坐标3,3,0的那条记录,所以查询任意粒子都会返回这个结果。
修复方案
修改Particle类的operator<,按坐标优先级依次比较即可:
bool operator<(const Particle& rhs )const{ if (loc[0] != rhs.loc[0]) return loc[0] < rhs.loc[0]; if (loc[1] != rhs.loc[1]) return loc[1] < rhs.loc[1]; return loc[2] < rhs.loc[2]; }
可选优化建议
- 可以用
std::tuple<int, int, int>作为conn的键类型,不需要自定义比较运算符,内存占用和查询效率都更高 - 如果粒子存在唯一ID属性,用ID作为键是最稳妥的方案
内容的提问来源于stack exchange,提问作者megamence
相关产品推荐
相关产品推荐

