C++代码与模板方法调用混淆

C++ code confusion with template method call

本文关键字:调用 模板方法 代码 C++      更新时间:2023-10-16

我使用的程序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. 这个电话不应该崩溃吗?它引用了一个nullptr!或者至少,这样做应该是危险的?如果我错了,请纠正我

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

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

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

DefaultEntryConstructor::ConstructHashMapEntry静态,因此在行中

e = constructor.ConstructHashMapEntry(e, key);

构造函数的从不使用(它是nullptr也无关紧要)-只有指针的type用于解析函数调用。


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

e = constructor.ConstructHashMapEntry(e, key);

它知道CCD_ 7的类型CCD_。因此,第一步是确定要调用的函数。根据此功能的类型,呼叫站点可以有四种类型之一:

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

请注意,虽然将静态方法称为constructor.ConstructHashMapEntry(e, key)而不是C::ConstructHashMapEntry(e, key)可能会让人感到困惑,但根据C的类型,这种形式允许FindOrCreateEntry同时使用静态非静态方法。