简体   繁体   English

Static std::hash function 对象

[英]Static std::hash function objects

C++ reference shows an example how to define custom hash function objects. C++ 参考显示了如何定义自定义 hash function 对象的示例。 In this example temporary hash<string> objects are created every time the call operator is executed:在此示例中,每次执行调用运算符时都会创建临时hash<string>对象:

namespace std
{
    template<> struct hash<S>
    {
        std::size_t operator()(S const& s) const noexcept
        {
            std::size_t h1 = std::hash<std::string>{}(s.first_name);
            std::size_t h2 = std::hash<std::string>{}(s.last_name);
            return h1 ^ (h2 << 1); // or use boost::hash_combine
        }
    };
}

I thought, would it be reasonable to make them static as they don't depend on any constructor arguments (default-constructible) and, basically, are just copies of each other?我想,将它们设为 static 是否合理,因为它们不依赖于任何构造函数 arguments (默认可构造)并且基本上只是彼此的副本?

namespace std
{
    template<> struct hash<S>
    {
        std::size_t operator()(S const& s) const noexcept
        {
            static std::hash<std::string> h;
            std::size_t h1 = h(s.first_name);
            std::size_t h2 = h(s.last_name);
            return h1 ^ (h2 << 1); // or use boost::hash_combine
        }
    };
}

Are there any disadvantages of this approach?这种方法有什么缺点吗?

What do you think is involved with creating these function objects?您认为创建这些 function 对象涉及什么? You are allocating them on the stack, not on the heap.您将它们分配在堆栈上,而不是堆上。 They don't have any members, so their size is zero.他们没有任何成员,因此他们的大小为零。 I guess a compiler might reserve a word for each of them on the stack, in order to give each one a unique this pointer... but that doesn't require any additional time, and I'd also expect the compiler to optimize this away since the class doesn't have any members and doesn't do anything with this .我猜编译器可能会在堆栈上为它们中的每一个保留一个词,以便为每个人提供一个唯一的this指针......但这不需要任何额外的时间,我也希望编译器能够优化this因为 class 没有任何成员,也没有对此做任何this

In other words, the compiler will probably figure out that std::hash<std::string>{}(s.first_name) is just a function call and compile it as such.换句话说,编译器可能会发现std::hash<std::string>{}(s.first_name)只是一个 function 调用并照此编译它。

I tried both methods and Clang 11.0.1 with -O3 at least generates the exact same code in both cases .我尝试了这两种方法和 Clang 11.0.1 与 -O3 至少在两种情况下生成完全相同的代码

In C++ static variables in inline function should be shared between all copies of that function.在 C++ static变量中,内联 function 应在该 ZC1C4254Z5268E683945D1 的所有副本之间共享Unused variables can be removed.可以删除未使用的变量。

So far not a problem for an executable, but is much harder to achieve in dynamic libraries as user code might use another compiler and/or different optimizations and thus might generate an actual reference to that object even if it unused in the library itself.到目前为止,对于可执行文件来说不是问题,但在动态库中实现起来要困难得多,因为用户代码可能使用另一个编译器和/或不同的优化,因此可能会生成对该 object 的实际引用,即使它在库本身中未使用。

I would expect some compilers on some platform to reserve 1 additional byte in data section and generate redundant export entry for such variable.我希望某些平台上的一些编译器会在数据部分中保留 1 个额外的字节,并为此类变量生成冗余导出条目。

PS: Example of ICC generating additional symbol (remove static to see the difference). PS:ICC生成附加符号的示例(删除static以查看差异)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM