3

我使用的程序 API 的文档缺少所需的信息,因此我尝试自己了解如何使用该HashMap::FindOrCreateEntry()方法。

template <typename C> Entry* FindOrCreateEntry(const K& key, C& constructor, Bool& created)
{
    /* ... */
    Entry* e = (Entry*) _allocator.Alloc(SIZEOF(Entry), C4D_MISC_ALLOC_LOCATION);
    if (!e)
    {
        created = false;
        return nullptr;
    }
    e = constructor.ConstructHashMapEntry(e, key);
    /* ... */
    return e;
}

我怀疑的部分是同名的第二种方法:

struct DefaultEntryConstructor
{
    static Entry* ConstructHashMapEntry(void* ptr, const K& key)
    {
        return new (ptr) Entry(key);
    }
};

Entry* FindOrCreateEntry(const K& key, Bool& created)
{
    return FindOrCreateEntry(key, *(DefaultEntryConstructor*) nullptr, created); //lint !e413
}
  1. 为什么没有模板参数传递给 的调用FindOrCreateEntry()
  2. 这个电话不应该崩溃吗?它取消引用 a nullptr!或者至少,这样做应该很危险?如果我错了,请纠正我。
4

1 回答 1

3

1 为什么没有模板参数传递给FindOrCreateEntry()的调用?

因为编译器可以从传递的参数中推断出类型。在这里,C = DefaultEntryConstructor

2 这个电话不应该崩溃吗?它取消引用一个 nullptr!或者至少,这样做应该很危险?如果我错了,请纠正我。

但是DefaultEntryConstructor::ConstructHashMapEntry静态的,所以在行

e = constructor.ConstructHashMapEntry(e, key);

构造函数的从不使用(它是否为 nullptr 无关紧要)——仅使用指针的类型来解析函数调用。


让我们更详细地看一下这个静态方法调用。当编译器实例化

e = constructor.ConstructHashMapEntry(e, key);

它知道C. constructor因此,第一步是识别要调用的函数。根据此函数的类型,调用站点可能具有以下四种类型之一:

  1. 常规的非虚拟方法调用:这将生成带有隐式this参数的常规方法调用,因此它使用对象引用的constructor
  2. 虚拟方法:这将使用某种机制(通常是 vtable)在运行时查找函数指针:查找和调用都依赖于对象引用或指针的
  3. 一个静态方法(我们的例子):这将生成一个没有隐式this参数的函数调用。这里只用到了对象的类型,完全忽略了
  4. 一个 constexpr:对象的运行时值显然不能影响这一点,所以不使用

constructor.ConstructHashMapEntry(e, key)请注意,虽然调用 static 作为而不是似乎令人困惑C::ConstructHashMapEntry(e, key),但这种形式允许FindOrCreateEntry使用处理静态非静态方法,具体取决于C.

于 2013-06-25T13:33:50.103 回答