C++运算符重载与vector STL问题:自定义字典排序及二分查找报错
问题原因与解决方案
1. 编译错误C2672、C2893的解决
你调用lower_bound时传参逻辑错误:该函数第三个参数是待匹配的目标值,要求和容器存储的元素类型(Dictionary)兼容,而你传入的是MatchString谓词对象,且只重载了Dictionary < MatchString的运算符,没有重载反向的MatchString < Dictionary,STL二分接口默认需要双向比较逻辑,因此触发编译失败。
可选修复方案:
- 方案1(最简便):给
Dictionary类重载operator<,排序和搜索逻辑统一基于_word字段的字典序:
// 全局运算符重载,或者定义为Dictionary的友元函数 bool operator<(const Dictionary& lhs, const Dictionary& rhs) { // 如需不区分大小写排序,可在此处将两个单词转小写后再比较 return lhs._word < rhs._word; }
调用lower_bound时直接传入构造的临时Dictionary对象即可:
it1 = lower_bound(list.begin(), list.end(), Dictionary{value});
- 方案2(自定义异类型比较):给
lower_bound传入第四个参数作为自定义比较器,支持Dictionary和string的双向比较:
struct DictCmp { bool operator()(const Dictionary& dict, const string& s) const { return dict._word < s; } bool operator()(const string& s, const Dictionary& dict) const { return s < dict._word; } }; // 调用时传比较器 it1 = lower_bound(list.begin(), list.end(), value, DictCmp{});
2. lower_bound和searchmanually结果不一致的解决
两个函数的匹配逻辑本身存在差异:
find_if是遍历所有元素,找第一个完全匹配的元素lower_bound是基于有序序列,找第一个不小于目标值的元素,返回值不代表一定匹配成功,需要额外判断元素值是否等于目标
除此之外要保证两个前提:
- 你的自定义归并排序的比较逻辑,和二分搜索的比较逻辑完全一致(比如排序是升序,搜索也按升序比较)
- 排序后的序列是严格按
_word字典序升序排列的,二分接口仅支持有序序列的搜索
修改后的二分搜索逻辑示例:
void binary_search_find_index(const vector<Dictionary>& list, const string& value) { auto it1 = lower_bound(list.begin(), list.end(), Dictionary{value}); // 额外判断是否真的匹配到目标值 if (it1 != list.end() && it1->_word == value) { auto idx1 = distance(list.begin(), it1); cout << "Index = " << idx1 << endl; } else { cout << "Can not find the value !." << endl; } }
3. 字母序排序开发建议
- 如有不区分大小写的排序需求,比较前先将所有单词统一转为全小写/全大写再比较,避免ASCII编码中大写字母优先级高于小写字母的问题(比如默认
"Apple" < "banana"是成立的,不符合日常字典序习惯) - 归并排序实现时注意边界判断,避免出现元素漏排、序对颠倒的问题,可以先用小批量测试数据(比如10个乱序单词)验证排序结果正确性,再用全量6万条数据测试
OOP开发优化建议
- 函数参数避免值传递大容器:你现有代码中
vector<Dictionary> list是值传递,每次调用都会拷贝整个6万条数据的容器,性能损耗极大,改为const vector<Dictionary>& list常量引用传递即可 - 成员变量封装:
vector<Dictionary>应该作为FastDictionary的私有成员变量,不需要作为参数在类方法中传递,外部调用类的搜索/排序接口时仅需传入必要参数(比如搜索的目标字符串) - 避免引用悬挂:你的
MatchString类中存储的是const string& s_,如果传入的是临时字符串对象,会导致引用失效,可改为直接存储string s_成员变量,牺牲极小性能避免稳定性问题 - 逻辑内聚:归并排序、文件加载逻辑都封装为
FastDictionary的私有方法,类对外仅暴露加载、搜索、打印等必要的公共接口,不要把内部实现细节暴露给外部调用者
内容的提问来源于stack exchange,提问作者Noob_one
相关产品推荐
相关产品推荐

