为什么简单地取消引用分配了 NULL 的指针不会崩溃

Why Simply de-referencing a pointer with NULL assigned is not crashing

 #include <iostream>
 int main()
 {
    int *ptr = NULL;
    // It does not crash
    *ptr; --------> Point-1
    //But this statment crashed
    std::cout<<"Null:"<<*ptr<<"\n"; ------> Point-2
    return 0;
 }

在上面的代码中,当我评论 "Point-2" 时代码没有崩溃。 但是,当我取消对 "Point-2" 的注释时,它崩溃了。 由于 ptr 是 NULL 理想情况下 Point-1 也应该崩溃。如果我错了,请纠正我。 有人能解释一下为什么当我简单地取消引用指针时代码没有崩溃吗?

取消引用空指针是未定义的行为。未定义的行为不等于错误。如果你触发了未定义的行为,任何事情都可能发生。如果你问的是另一种方式:

Why is undefined behavior not causing an error instead of giving us strange behavior?

可能有很多原因。原因之一是性能。例如,在 std::vector 的实现中(至少在 MSVC 中),在 Release Mode 中没有检查索引是否 out of range。您可以尝试这样做:

std::vector<int> v(4);
v[4]=0;

它将编译并运行。你可能会有奇怪的行为,也可能不会。但是,在调试模式下,它会在 运行 时抛出异常。 MSVC 在调试模式下进行检查,因为在调试模式下性能并不重要。但它不在发布模式下,因为性能很重要。

这同样适用于取消引用空指针。您可以想象取消引用的代码将像这样放在包装器中:

//Imaginary code
T& dereference(T* ptr){
    if(ptr==nullptr){
        throw;
    }
    return *ptr;
}

这部分:if(ptr==nullptr){throw;} 将减慢上下文中每个指针的取消引用过程,这是不可取的。

不过,也可以这样做:

//Imaginary code
T& dereference(T* ptr){
    #ifdef DEBUG
    if(ptr==nullptr){
        throw;
    }
    #endif
    return *ptr;
}

我想你现在明白了。

在第 2 点中,您尝试显示 0x0 地址的内容,这会产生访问冲突错误。

在第 1 点中,您什么都不做,因此程序不必访问该指针所描述的内存。这不会产生访问冲突错误。