C++:*((SomeType*)0)?

non*_*ot1 2 c++ pointers initialization

我几次遇到这个句法结构,我想知道:

  1. 这是做什么的?
  2. 设计推理可能是什么?

它往往看起来像这样:

struct SubType : public SomeSuperType {

    SubType(int somthing) : SuperType(something), m_foo(*((FooType *)0))
    {}

    private:
    FooType m_foo;
}
Run Code Online (Sandbox Code Playgroud)

要清楚,代码有效.但目的是什么?m_foo没有那条线的状态是什么?

AnT*_*AnT 6

这个结构的目的是SomeType在你正式需要一个对象但不想要或不能声明一个对象的情况下模拟一个假的未命名对象.它有其有效用途,并不一定会导致未定义的行为.

一个典型的例子是确定某个类成员的大小

sizeof (*(SomeClass *) 0).some_member
Run Code Online (Sandbox Code Playgroud)

或者类似的decltype应用

decltype((*(SomeClass *) 0).some_member)
Run Code Online (Sandbox Code Playgroud)

以上示例都不会导致任何未定义的行为.在非评估的上下文中,表达式*(SomeClass *) 0完全合法且有效.

您还可以在语言标准本身中看到此技术用于说明目的,如8.3.5/12

对于在declarator-id之前指定更复杂的类型,trailing-return-type最有用:

template <class T, class U> auto add(T t, U u) -> decltype(t + u); 
Run Code Online (Sandbox Code Playgroud)

而不是

template <class T, class U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);
Run Code Online (Sandbox Code Playgroud)

观察如何(*(T*)0) + (*(U*)0)表达下使用decltype来执行结果类型的二进制的编译时间预测+类型之间操作者TU.

当然,再次,这些技巧仅在非评估的上下文中使用时才有效,如上所示.

有时它被用作"空引用"的初始化器,如

SomeType &r = *(SomeType *) 0;
Run Code Online (Sandbox Code Playgroud)

但这实际上跨越了合法的边界并产生了未定义的行为.

您在特定示例中的内容无效,因为它尝试在计算上下文中访问无效的"null左值".

PS在C语言中,还有一个特殊的规范部分,即运算符&*相互抵消,这意味着&*(SomeType *) 0有效并保证评估为空指针.但它没有扩展到C++.


Pup*_*ppy 5

这是做什么的?未定义的行为.

设计推理可能是什么?希望导致未定义的行为.没有其他理由.