std::map 键的要求(设计决策)

2024-02-24

当我做一个std::map<my_data_type, mapped_value>,C++ 对我的期望是my_data_type有它自己的operator<.

struct my_data_type
{
    my_data_type(int i) : my_i(i) { }

    bool operator<(const my_data_type& other) const { return my_i < other.my_i; }

    int my_i;
};

原因是你可以得出operator> and operator== from operator<. b < a暗示a > b,所以有operator>. !(a 意思是a不小于b也不大于它,所以它们必须相等。

问题是:为什么 C++ 设计者没有要求operator==明确定义?明显地,operator==是不可避免的std::map::find()并从中删除重复项std::map。为什么要实现 5 个操作并调用一个方法两次,以免迫使我显式实现operator==?


operator==是不可避免的std::map::find()

这就是你犯了严重错误的地方。map不使用operator==无论如何,这并不是“不可避免的”。两把钥匙x and y就地图而言,如果!(x < y) && !(y < x).

map不知道也不关心你是否已经实现operator==。即使有,也不必是顺序中所有等效键都相等的情况operator==.

所有这一切的原因是,只要 C++ 依赖顺序(排序、映射、集合、二分搜索),它所做的一切都基于“严格弱顺序”这一​​易于理解的数学概念,该概念也在标准中定义。没有特别需要operator==,如果您查看这些标准函数的代码,您不会经常看到类似的内容if (!(x < y) && !(y < x))这使得两个测试紧密结合。

此外,这些都不一定基于operator<。默认比较器为map is std::less<KeyType>,默认情况下使用operator<。但如果你有专门的std::less for KeyType那么你不需要定义operator<,如果您为地图指定不同的比较器,那么它可能有也可能没有任何关系operator< or std::less<KeyType>。所以我说过的地方x < y上面,确实是cmp(x,y), where cmp是严格的弱顺序。

这种灵活性是不拖拉的另一个原因operator==进去。认为KeyType is std::string,并且您指定自己的比较器来实现某种特定于区域设置的、不区分大小写的排序规则。如果map used operator==有时,那么这将完全忽略这样一个事实:仅大小写不同的字符串应该被视为相同的键(或在某些语言中:与出于排序目的而被认为无关紧要的其他差异)。所以平等比较会also必须是可配置的,但程序员只能提供一个“正确”答案。这不是一个好情况,您永远不希望您的 API 提供看起来像定制点但实际上并非如此的东西。

此外,这个概念是,一旦你排除了树中小于你正在搜索的键的部分,以及树中键小于它的部分,剩下的都是空的(没有找到匹配)或者其中有一个密钥(找到匹配)。所以,你已经使用过current < key then key < current,除了等价之外没有其他选择。情况恰恰是:

if (search_key < current_element)
    go_left();
else if (current_element < search_key)
    go_right();
else
    declare_equivalent();

你的建议是:

if (search_key < current_element)
    go_left();
else if (current_element < search_key)
    go_right();
else if (current_element == search_key)
    declare_equivalent();

这显然是不需要的。事实上,它是your建议效率较低!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

std::map 键的要求(设计决策) 的相关文章

随机推荐