You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何当T为指针类型时std::unordered_multiset的==运算符返回错误结果?

编译器Bug还是使用错误?自定义指针哈希/相等仿函数后unordered_multiset比较不生效

我为指针类型提供了哈希和相等仿函数,但unordered_multiset的相等比较似乎不生效,还特意写了自定义模板容器测试这些仿函数。

哈希仿函数

class CharPtHash
{
private:
    using pChar = char*;
public:
    size_t operator()(const pChar& c) const
    {
        std::hash<char> hasher;
        if (c == nullptr)
        {
            return 0;
        }
        return hasher(*c);
    }
};

相等仿函数

class CharPtEqual
{
private:
    using pChar = char*;
public:
    bool operator()(const pChar& lhs, const pChar& rhs)const
    {
        if (lhs == rhs)
        {
            return true;
        }
        else if (lhs==nullptr || rhs==nullptr)
        {
            return false;
        }
        return *lhs == *rhs;
    }
};

测试代码

#include <iostream>
#include <unordered_set>
using namespace std;

// 此处省略上述哈希/相等仿函数定义

// 自定义unordered_multiset输出重载(假设用户实现了此部分)
template <typename T, typename Hash, typename Equal>
ostream& operator<<(ostream& os, const unordered_multiset<T, Hash, Equal>& ms) {
    os << "{ ";
    for (const auto& elem : ms) {
        os << *elem << ", ";
    }
    os << "\b\b }";
    return os;
}

int main()
{
    cout << "Testing unordered_multiset with keys being simple types:\n";
    unordered_multiset<char> sA1({ 'a','b','c' });
    unordered_multiset<char> sA2({ 'a','c','b' });

    cout << "Values: " << endl << sA1 << endl << sA2 << endl;

    cout << (sA1 == sA2 ? "Equal" : "Not Equal");
    cout << endl;

    cout << "Testing unordered_multiset with keys being pointers to simple types:\n";
    char** c1 = new char* [3]{ new char('a'), new char('b'), new char('c') };
    char** c2 = new char* [3]{ new char('a'), new char('c'), new char('b') };

    unordered_multiset<char*,CharPtHash,CharPtEqual> sB1;
    unordered_multiset<char*,CharPtHash,CharPtEqual> sB2;

    sB1.insert(c1[0]);
    sB1.insert(c1[1]);
    sB1.insert(c1[2]);
    sB2.insert(c2[0]);
    sB2.insert(c2[1]);
    sB2.insert(c2[2]);

    cout << "Values: " << endl << sB1 << endl << sB2 << endl;

    cout << (sB1 == sB2 ? "Equal" : "Not Equal");
    cout << endl;

    // 手动释放内存
    for (int i = 0; i < 3; ++i) {
        delete c1[i];
        delete c2[i];
    }
    delete[] c1;
    delete[] c2;

    cin.get();
}

输出结果

Testing unordered_multiset with keys being simple types:
Values:
{ a, b, c }
{ a, c, b }
Equal
Testing unordered_multiset with keys being pointers to simple types:
Values:
{ a, b, c }
{ a, c, b }
Not Equal

这不是你的使用错误,而是Visual Studio标准库中unordered_multiset的operator==实现不符合C++标准的问题。

根据C++标准,无序容器的相等比较仅需满足两个条件:容器大小相同,且每个等价元素的数量一致(等价性由自定义相等谓词定义),与元素的存储顺序无关。但Visual Studio的实现中,unordered_multiset的operator==会按迭代器顺序逐个比较元素,导致元素顺序不同但等价数量一致的容器被判定为不相等。

你可以通过手动验证等价元素数量的方式替代默认的operator==,示例如下:

bool areEqual(const unordered_multiset<char*, CharPtHash, CharPtEqual>& a, 
              const unordered_multiset<char*, CharPtHash, CharPtEqual>& b) {
    if (a.size() != b.size()) return false;
    for (const auto& elem : a) {
        if (a.count(elem) != b.count(elem)) {
            return false;
        }
    }
    return true;
}

调用此函数即可得到符合标准的相等判断结果。

另外,你的哈希与相等仿函数满足C++标准要求的一致性(相等的元素哈希值必然相同),这部分实现是正确的。

内容的提问来源于stack exchange,提问作者Software Carpenter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 11:21:01