IID_PPV_ARGS 和取消引用 NULL

IID_PPV_ARGS and Dereferencing NULL

我正在做的一个项目 MSDN documentation 有这样的代码:

IFileOpenDialog *pFileOpen;
IID_PPV_ARGS(&pFileOpen)

其中 IID_PPV_ARGS 是:

#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), IID_PPV_ARGS_Helper(ppType)

我的问题是关于 **(ppType) 部分的。这不会最终取消对空指针或未初始化指针的引用吗?为什么这样做有效?

__uuidof() 是专有的 Microsoft 扩展,编译器知道如何处理。它是在编译时评估的,而不是在 运行 时间。

编译器尝试查找并替换给定接口的 UUID。该接口使用 __declspec(uuid("...")) 扩展声明其 UUID。如果编译器找不到 UUID,构建将失败。在 运行 时间实际上没有指针被取消引用。

ppType 设置为 IFileOpenDialog**,因此 *(ppType)IFileOpenDialog***(ppType)IFileOpenDialog。因此,__uuidof(**(ppType)) 在编译时被评估为 __uuidof(IFileOpenDialog)

这样做是一样的:

char* ptr = nullptr;
size_t charSize = sizeof(*ptr);

sizeof(*ptr) 在编译时将被评估为 sizeof(char),即使 ptr 为空。

Jonathan 的回答加一分(因为我的声誉太低无法发表评论):

在调试版本中,__uuidof 总是 动态初始化一个对象(在运行时)。在发布版本中,__uuidof 可以静态(在编译时)初始化一个对象。

参见:https://docs.microsoft.com/en-us/cpp/cpp/uuidof-operator?view=msvc-160