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

C++ C++;:*((SomeType*)0)?,c++,pointers,initialization,C++,Pointers,Initialization,我曾多次遇到这种句法结构,我想知道: 这有什么用 设计推理可能是什么 它看起来像这样: struct SubType : public SomeSuperType { SubType(int somthing) : SuperType(something), m_foo(*((FooType *)0)) {} private: FooType m_foo; } 明确地说,代码是有效的。但目的是什么?如果没有这一行,mêfoo的状态会是什么?这是做什么的?未定

我曾多次遇到这种句法结构,我想知道:

  • 这有什么用
  • 设计推理可能是什么
  • 它看起来像这样:

    struct SubType : public SomeSuperType {
    
        SubType(int somthing) : SuperType(something), m_foo(*((FooType *)0))
        {}
    
        private:
        FooType m_foo;
    }
    

    明确地说,代码是有效的。但目的是什么?如果没有这一行,
    mêfoo
    的状态会是什么?

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


    设计推理可能是什么?引起未定义行为的欲望。没有其他理由。

    此构造的目的是在您正式需要对象,但不想要或无法声明真实对象的情况下,模拟类型为
    SomeType
    的伪未命名对象。它有其有效的用途,不一定会导致未定义的行为

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

    sizeof (*(SomeClass *) 0).some_member
    
    或decltype的类似应用程序

    decltype((*(SomeClass *) 0).some_member)
    
    上述两个示例都不会导致任何未定义的行为。在未计算的上下文表达式中,如
    *(SomeClass*)0
    是完全合法和有效的

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

    尾随返回类型对于更复杂的类型最有用 在声明器id之前指定很复杂:

    template <class T, class U> auto add(T t, U u) -> decltype(t + u); 
    
    但这实际上跨越了法律的界限,产生了未定义的行为

    您在特定示例中拥有的内容是无效的,因为它试图访问评估上下文中的无效“null左值”


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

    我不认为这个例子一定是ub。它取决于
    FooType
    的定义。假设
    Foo
    是一个空类,其构造函数执行以下操作:

    class Foo {
      public:
        Foo() { std::cout << "Hey, world! A new Foo just arrived.\n"; }
        // I think the default copy and assign constructors do nothing
        // with an empty type, but just in case:
        Foo(const Foo&) {}
        Foo& operator=(const Foo&) { return *this; }
    };
    
    class-Foo{
    公众:
    
    Foo(){std::难道它能让编译器自由地按照自己的意愿行事,包括启动NetHack,或生成它认为合适的任何可执行文件,而不考虑程序中的任何其他内容。为什么有人希望发生这种情况,我不知道。@R.MartinhoFernandes gustiority。普通的好奇心。除非你是一只猫,否则你应该是安全的。所以它将一个空指针投射到(FooType*),并将其内容分配给m_foo。从顶部看,我只能想到两种可能有用的情况:在内存地址0处有有用信息的嵌入式上下文中,或者故意触发异常。您在什么上下文中看到此代码?@BennySmith,即使在您认为可能有用的情况下也是如此,你也必须从编译器那里得到某种保证;编译器可能会拒绝编译代码(如果它能证明它将被调用),或者生成一些陷阱生成代码,从而导致它在运行时崩溃。(g++在某些未定义行为的情况下会这样做。我不知道这是否是其中之一。)我猜这是一个测试代码,它设计成一个内存异常。这是一个很好的答案。虽然它是未定义的C++行为,但它可能在特定的平台上有很好的行为定义,因此对作者来说是有用的。它只是在提供的例子中没有定义。介绍时,它似乎只是一个例子。问题本身似乎是关于一般的
    *(T*)0
    。一般来说
    *(T*))0
    不一定会导致未定义的行为。实际上,这有一个可能的用途:如果
    FooType
    有多个重载构造函数,这将确保调用正确的构造函数。虽然要使此特定示例起作用,
    FooType
    的复制构造函数将永远不使用其参数,这似乎很粗略,充其量。@Xavier Holt:好吧,从形式上讲,这仍然是一种行为未定义的黑客行为。在已计算的上下文中取消对空指针的引用本身就是一种攻击,无论您是否访问结果左值。
    SomeType &r = *(SomeType *) 0;
    
    class Foo {
      public:
        Foo() { std::cout << "Hey, world! A new Foo just arrived.\n"; }
        // I think the default copy and assign constructors do nothing
        // with an empty type, but just in case:
        Foo(const Foo&) {}
        Foo& operator=(const Foo&) { return *this; }
    };
    
    Foo(*static_cast<Foo*>(0));