C++ 可访问的空指针

C++ 可访问的空指针,c++,pointers,exception,null,delete-operator,C++,Pointers,Exception,Null,Delete Operator,我想知道为什么下面的小程序不会引起NullPointerException。 有什么想法吗? 输出是2倍Hello World!!!在我的macbook上使用clang-500.2.79 #include <iostream> using namespace std; class Strange { public: Strange() {} virtual ~Strange() {} void sayHello() { cout<&l

我想知道为什么下面的小程序不会引起NullPointerException。 有什么想法吗? 输出是2倍Hello World!!!在我的macbook上使用clang-500.2.79

#include <iostream>

using namespace std;

class Strange {
public:
    Strange() {}
    virtual ~Strange() {}
    void sayHello() {
        cout<<endl<<"Hello World!!!"<<endl;
    }

};

int main(void) {
    Strange* s = new Strange();
    delete s; s = NULL;
    s->sayHello();
    (*s).sayHello();
    return 0;
}
#包括
使用名称空间std;
类奇怪{
公众:
奇怪的(){}
虚拟~奇怪(){}
void sayHello(){
coutC++没有“NullPointerException”。取消引用null指针只是未定义的行为,任何事情都可能发生

在您的情况下,
sayHello()
根本无法访问
*此
,因此它恰好“正常”工作(在您的编译器、优化设置、运行时和硬件上)。但这并不能保证。未定义的行为只是未定义的;程序也可能崩溃或在线订购比萨饼

我想知道为什么下面的小程序不会引起NullPointerException

因为它是C++,而不是一种“托管”语言,它对每个操作都进行昂贵的运行时间检查。如果您引用空指针,就不会有异常;您将得到某种未定义的行为。 在这种情况下,成员函数不访问对象,因此(在大多数实现中)它的行为就像指针是有效的一样。如果它确实访问了对象,那么您可能会遇到运行时故障,或者内存损坏,导致细微的错误和失眠


尽可能避免使用指针和
new
;必要时使用智能指针和其他技术。如果指针可能为空,则在取消引用之前检查它。

不完全正确……我预计空取消引用会出现分段错误。然而,我确实认为编译器优化会忽略引用操作,因为函数不使用
参数,所以不会发生实际的取消引用。@不朽:仅当内存被访问时,且仅当指针指向不可访问的内存页时,且仅当硬件支持内存保护时。分段故障是硬件级故障,仅由一次访问内存的实际尝试;它对软件级的概念一无所知,比如解引用。我尝试了几次编译器优化,也尝试了最新的gcc(从-O0到O3),输出始终正常,我从未遇到任何seg故障或其他异常:(@user3392371:的确;如果您确实试图通过指针访问内存,那么您的代码不会通过优化级别访问内存。它只是将空指针作为
this
传递给函数,然后忽略它。如果您将函数
设为虚拟的
,或者添加成员变量并进行读写操作,则会得到SEGFULT在函数中,你可能会出错。更好的是:首先避免未定义的行为。谢谢你的解释!所以它工作的原因是成员函数没有访问对象。有了这些信息,我可以继续玩…大Thx!!!谢谢你的回答。所以我有未定义的行为或者在将指针设置为NULL之后。如果我不将指针设置为NULL,我会有一个悬空指针,对吗?它也有一些未定义的行为,可能更糟……那么我如何避免这种未定义的行为呢?@user3392371将指针设置为NULL不是UB。取消引用这样的指针就是UB(与解除对unitilialised或othwerwise悬挂指针的引用一样)。解决方案取决于您的情况:如果指针可以为null,请在使用之前对其进行测试:
if(s)s->sayHello();
。如果指针非null是代码的先决条件,请将其记录为相应的调用(即确保指针实际不为null)。在这种情况下,您还可以
assert()
确认它不为null,这将使您在调试版本中进行错误检查。