“dynamic_cast”实际上可以解除引用后的NULL指针吗?

时间:2011-06-06 06:48:09

标签: c++ visual-studio-2010 visual-c++

以下代码正确编译并获得神秘的输出:

  

特殊投资功能   00000000

(环境:C ++ VS2010)

#include <iostream>
#include <vector>
using namespace std;

class Security {
public:
  virtual ~Security() {}
};

class Stock : public Security {};

class Investment : public Security {
public:
  void special() {
    cout << "special Investment function" << endl;
  }
};

int main() {
  Security* p = new Stock;
  dynamic_cast<Investment*>(p)->special();
  cout << dynamic_cast<Investment*>(p) << endl;
  return 0;
}

怎么可能?取消引用NULL指针并获得“正确”输出而不是崩溃? 它是VS2010的特殊“特征”吗?

现在我明白了。我做了一个测试,似乎在“特殊”功能中解除引用“this”会导致程序崩溃。

感谢您的帮助。

8 个答案:

答案 0 :(得分:7)

取消引用空指针是未定义的行为 - 您可能会得到意外的结果。请参阅this very similar question

在这种情况下,Investment::special()以非虚方式调用,因此您可以认为编译器只是创建了一个全局函数

Investment_special_impl( Investment* this )

并调用它将null this指针作为隐式参数传递。

你不应该依赖于此。

答案 1 :(得分:4)

这是'未定义的bahviour'。将方法视为具有隐含参数,带有'this'。在您的情况下,NULL被作为'this'的实际参数传递。由于您没有引用“this”引用的任何对象数据(隐式或显式),因此它没有崩溃。

如果该方法是虚拟的,它很可能已经崩溃,因为虚拟调用通常通过与该对象关联的查找表进行调度(因此'this')。

由于编译器编写者可以随意实现“this”和虚拟成员查找表,因此您不应该依赖于此行为。这是未定义的。

答案 2 :(得分:2)

在大多数C ++实现中,非虚方法不需要调用有效实例(不检查this会更快,因为标准不需要它)。

您可以将指针设置为NULL,如果您不访问实例字段,方法仍然会成功。

虚方法需要有效vtable,因此它们总是取消引用对象并在未初始化时导致错误。

答案 3 :(得分:2)

在这里,你无处取消引用空指针:你只需要调用函数Investment :: special(NULL),它是非虚拟的,并且在它的主体中不会取消引用它。尽管规范可能告诉我这是未定义的行为,但是编译器完全理解为不在此处进行任何解除引用,因此程序不会崩溃。

答案 4 :(得分:1)

解除引用 任何 NULL指针是Undefined Behaivor。

答案 5 :(得分:1)

您不应该取消引用NULL指针,因为它可能导致Undefine Behavior。为什么你的代码有效是因为在方法中:

void special() {
  cout << "special Investment function" << endl;
}

你真的没有提到this。要进行演示,只需在Investment类中声明一个变量,然后尝试在special()内打印它。你会崩溃。

答案 6 :(得分:0)

取消引用空指针会调用未定义的行为,无论您是如何获得空指针,无论是dynamic_cast还是其他内容。

答案 7 :(得分:0)

我不确定取消引用NULL问题,但我可以解释代码的行为。

<强>的dynamic_cast&LT;投资*&gt;(p) - &gt; special();

打印:“特殊投资功能”

cout&lt;&lt; dynamic_cast&lt;投资*&gt;(p)&lt;&lt; ENDL;

打印:“0xABABABA”&lt; - 实例p的内存地址

就像跑步一样:

cout&lt;&lt; p <&lt; ENDL;