自定义Tenor为键的C++ map:大小为3却仅迭代2元素,值获取异常
自定义结构体作为std::map键的问题分析与修复
问题根源
你的核心问题在于Tenor结构体的operator<实现完全不符合std::map要求的严格弱序规则,导致map的内部平衡树结构彻底混乱,所有依赖该规则的操作(插入、查找、遍历)都出现了未定义行为。
问题1:为何for循环仅迭代2个元素?
std::map依赖operator<维护内部的有序平衡树。你的operator<始终返回true,违反了严格弱序的核心规则:
- 自反性:任何对象不能小于自身,但你的实现中
a < a会返回true - 不对称性:如果
a < b为真,那么b < a必须为假,但你的实现中两者都为真
这种错误直接破坏了map的内部结构,遍历过程无法正确访问所有节点,虽然size()显示存在3个元素,但实际遍历只能输出部分节点,属于未定义行为的典型表现。
问题2:为何item并非map中对应键的Value?
std::map::find()依赖operator<判断键的等价性:当!(a < b) && !(b < a)时,map认为a和b是等价键。你的实现中,任意两个Tenor对象都会满足a < b和b < a同时为真,导致find无法正确匹配目标键,返回的迭代器可能是无效位置(比如end()),访问其second成员会读取到内存垃圾,也就是你看到的随机数值。
修复方案
正确实现operator<,基于Tenor的_label成员进行字符串比较,满足严格弱序要求:
#include <iostream> #include <map> using namespace std; struct Tenor { public: string _label; Tenor(string label = "3M") { _label = label; } // 基于_label字典序的严格弱序实现 bool operator<(Tenor const& obj) const { return _label < obj._label; } }; void tenor_operator_ordered() { auto t1 = Tenor {"1M"}; auto t2 = Tenor {"2M"}; auto t3 = Tenor {"3M"}; map<Tenor, int> mp; mp[t1] = 1; // 插入元素 mp[t3] = 3; mp[t2] = 2; // 验证元素查找 int item; item = mp.find(t1)->second; std::cout << item << '\n'; item = mp.find(t2)->second; std::cout << item << '\n'; item = mp.find(t3)->second; std::cout << item << '\n'; cout << "Size: " << mp.size() << endl; // 遍历输出有序元素 for (auto x : mp) cout << x.first._label << " " << x.second << endl; } int main() { tenor_operator_ordered(); return 0; }
修复后的输出
1 2 3 Size: 3 1M 1 2M 2 3M 3
内容的提问来源于stack exchange,提问作者Anatoly Bugakov
相关产品推荐
相关产品推荐

