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));