【问题标题】:Why isn't std::hash<T> specialized for char*?为什么 std::hash<T> 不专门用于 char*?
【发布时间】:2013-04-09 07:13:38
【问题描述】:

为什么 C++ 标准不指定 std::hash&lt;T&gt; 专用于 char*const char*unsigned char*const unsigned char* 等?即,它将散列 C 字符串的内容,直到找到终止的 null。

将我自己的专业化注入我自己的代码的std 命名空间有什么害处吗?

【问题讨论】:

  • 我会说char*unsigned char* 在散列的上下文中是不安全的,其他带有const 限定符的都可以。不要注入std::,只需在你的命名空间中进行特化。
  • 您的std::hash 存储的const char* 的生命周期是多少? (std::hash 存储它的键值以及散列它们)。你如何区分以空结尾的const char* 和指向单个字符的指针?
  • std::hash 只是一个函子对象。它散列了它的论点。它不存储它。
  • 完全有效的问题和答案由事实和参考文献支持。投票重新开放。
  • 相关:std::hash value on char* value and not on memory address? - 即如果您想知道如何实际散列 C 字符串然后...

标签: c++ hash stl stdhash


【解决方案1】:

char*(及其同类)并不总是意味着字符串。它们可以是简单的字节数组或二进制文件转储或任何数量的其他东西。如果你的意思是 C++ 中的字符串,你通常使用“字符串”类。

至于创建自己的,鉴于上述情况,这是一个坏主意。但是,对于用户定义的类型,可以在 std:: 命名空间中创建 std:: 函数的特化。

【讨论】:

  • 关于 char* 在 C++ 标准库中被视为指向空终止缓冲区的指针的唯一时间是在从 C 代码继承的 std::string 和某些 @987654323 中@ 代码。我想不出别的地方了?
  • 我知道char* 并不总是 表示字符串。我想知道的是你的答案是不是 C++ 标准委员会的想法。
  • it is acceptable to create specializations of the std:: functions in the std:: namespace. 是吗?
  • 很难知道他们在想什么,但我认为既然他们的代码必须是所有人的一切,这肯定是一个考虑因素。我相信明确不允许专门化 const char*,但我目前找不到参考
  • 引用 C++0x N3000 草案,17.6.3.2.1.1(但标准应该包含类似的部分):“[...] 程序可以为任何标准添加模板特化仅当声明依赖于用户定义的外部链接类型并且特化满足原始模板的标准库要求并且未明确禁止时,库模板才将其命名为 std 命名空间。"
【解决方案2】:

为什么 C++ 标准不指定 std::hash&lt;T&gt; 专用于 char*const char*unsigned char*const unsigned char* 等?

看起来它来自proposal N1456。 (强调我的)

一些早期的哈希表实现对 char* 进行了特殊处理:它专门使用默认哈希函数来查看指向的字符数组,而不是指针本身。该提案取消了这种特殊待遇。特殊处理使得对 C 字符串使用哈希表稍微容易一些,但代价是消除了一致性并使得编写通用代码变得更加困难。因为通常期望天真的用户使用 std::basic_string而不是 C 字符串,特殊处理的成本大于收益。

如果我的解释正确,原因是支持 C 风格的字符串会破坏通常作用于指针散列的代码。

将我自己的专业化注入我自己的代码的 std 命名空间有什么害处吗?

有潜在的危害,是的。

  • 将来,您添加到 std 命名空间的任何内容都可能与新符号名称发生冲突。
  • 目前,您添加到 std 命名空间的任何内容都可能与标准库的其他组件“更好地匹配”,从而无声地破坏行为。

【讨论】:

    【解决方案3】:

    指针类型有一个标准的特化,see here

    template< class T > struct hash<T*>;
    

    所以,它也可以覆盖char*(作为字节序列而不是 C 风格的字符串)。

    如果您的意思是专门针对 C 风格的字符串,那么实现它在技术上没有问题。但由于在 C++ 中对 std::string 进行了特化,因此对 C 风格的字符串进行特化是不值得的。

    对于问题的第二部分,您可以在 std 命名空间中注入所有内容,但是,您会得到什么?这违背了命名空间的目标。拥有自己的命名空间区域。

    【讨论】:

    • 有些努力是值得的,因为如果使用 char* 作为 key,如果我们使用 string hash ,我们将需要为每个 hash 支付额外的内存分配和复制。
    猜你喜欢
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 2015-07-05
    • 2017-11-10
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多