【问题标题】:Treat a pointer as unsigned int for hash将指针视为散列的无符号整数
【发布时间】:2015-08-23 15:26:47
【问题描述】:

我想为我的自定义类型 AnimationSet 重载 std::hash 模板:

struct AnimationSet {
    const AnimationData *animationData;
    SceneNode *sceneNode;

    bool operator==(const AnimationSet &other) const {
        return ( this->animationData == other.animationData &&
                 this->sceneNode == other.sceneNode );
    }
};

如您所见,它是一个仅包含两个指针的结构。

将这些指针转换为 unsigned int 以计算 AnimationSet 的哈希值是否合法?

namespace std {
    template<>
    struct hash<AnimationSet> {
        size_t operator()(const AnimationSet &set) const {
            hash<unsigned int> h;

            return h((unsigned int)set.animationData) ^ h((unsigned int)set.sceneNode);
        }
    };
}

编辑: 我在哈希重载的背景下问这个问题,但我想知道更一般问题的答案:“将任何指针强制转换为 unsigned int 是否公平?”

【问题讨论】:

  • 关于您的“一般性问题”,请参考this
  • std::hash 已经专门用于指针,因此您无需转换即可进行散列。可以直接使用hash&lt;const AnimationData *&gt;hash&lt;SceneNode *&gt;

标签: c++


【解决方案1】:

一般来说,不,指针不一定与unsigned int 大小相同。特别是,在大多数 64 位系统上,它们将是两倍大,因此您所要做的就是取指针的最低有效 32 位,这更有可能导致冲突(尤其是因为许多指针没有最低的两位设置,所以你只得到 30 位有助于散列值的有用信息)。

您应该 #include &lt;cstdint&gt; 并改为转换为 std::uintptr_t。这是一种无符号整数类型,保证能够存储指针的值而不会丢失任何位。

【讨论】:

  • 我不知道标准有这样的类型,我已经习惯了微软的 UINT_PTR 等价物。 +1。
【解决方案2】:

虽然指针确实只是一个无符号整数值(至少在现代类似 PC 的系统上),但不确定是否可以使用 unsigned int。请记住,int 的大小和指针的大小可能不同(例如,在 64 位系统上)。

如果您想要一个足够大以容纳指针的整数类型,请使用&lt;cstdint&gt; 中的uintptr_t

【讨论】:

  • 指针并不总是只是一个无符号整数值; C++ 可以与旧的分段 16 位 x86 等奇怪的架构一起使用,并且总是需要考虑成员指针。
猜你喜欢
  • 1970-01-01
  • 2014-05-12
  • 2012-09-18
  • 2017-04-02
  • 1970-01-01
  • 1970-01-01
  • 2010-12-21
  • 2012-05-09
  • 1970-01-01
相关资源
最近更新 更多