标准::地图比较指针

std::map comparing pointers

本文关键字:指针 比较 地图 标准      更新时间:2023-10-16

我将如何在下面的示例中实现比较运算符,以使ObjectPair( &a, &b )等于ObjectPair( &b, &a )? 此外,我将如何使用stdext::hash_map而不是std::map来实现这一点?

struct ObjectPair
{
    public:
        ObjectPair( Object* objA, Object* objB )
        {
            A = objA;
            B = objB;
        }
        bool operator<( const ObjectPair& pair ) const
        {
            // ???
        }
        Object* A;
        Object* B;
};
int main()
{
    std::map< ObjectPair, int > pairMap;
    Object a;
    Object b;
    pairMap[ ObjectPair(&a, &b) ] = 1;
    pairMap[ ObjectPair(&b, &a) ]++;    
    /// should output 2
    std::cout<< pairMap[ ObjectPair( &a, &b ) ] << std::endl;
    return 0;
}

你的根本问题是你需要实现operator<,这样它就不会区分ab,但为所有不相等的对象返回一致的结果。

最简单的方法可能是对指针进行排序,然后进行比较。类似的东西

bool operator<(const ObjectPair& pair) const {
    // Technically < is unspecified on most object pointers
    // but std::less<T> is guaranteed to have a total ordering
    std::less<Object*> comp;
    Object *ourlow = std::min(a, b, comp);
    Object *ourhigh = std::max(a, b, comp);
    Object *theirlow = std::min(pair->a, pair->b, comp);
    Object *theirhigh = std::max(pair->a, pair->b, comp);
    if (comp(ourlow, theirlow)) return true;
    if (comp(theirlow, ourlow)) return false;
    return comp(ourhigh, theirhigh);
    }
    return false;
}

当然,这是假设Object不可排序,因此我们只关心指针值是否相同。如果Object本身有排序,那么您可能应该调用Object::operator<(),而不仅仅是在指针上使用<,即 if (*ourlow < *theirlow)


为了使这项工作在std::unordered_map中完成(这是C++11的事情,我假设stdext::hash_map是等价的),那么你需要实现operator==并专门针对你的对象进行std::hash<>。为了您的专业化,您可能只想对两个指针进行哈希处理并组合值(使用类似 bitwise-xor 的东西)。


附加到

这个问题的很长的评论线程的要点与C++标准对指针比较的说法有关。也就是说,比较不是同一对象/数组成员的相同类型的两个对象指针会调用未指定的行为。一般来说,这在任何具有单个统一内存系统的架构(即您可能使用的任何架构)上都无关紧要,但符合标准仍然很好。为此,比较都改为使用std::less<Object*>,因为C++标准保证std::less<T>有一个总的排序。