C++ 为什么简单地取消引用赋值为NULL的指针不会崩溃 #包括 int main() { int*ptr=NULL; //它不会崩溃 *ptr;----------->第1点 //但这座车站撞毁了 std::cout

C++ 为什么简单地取消引用赋值为NULL的指针不会崩溃 #包括 int main() { int*ptr=NULL; //它不会崩溃 *ptr;----------->第1点 //但这座车站撞毁了 std::cout,c++,undefined-behavior,C++,Undefined Behavior,取消引用空指针是未定义的行为。未定义的行为不等于错误。如果触发未定义的行为,则可能发生任何情况。如果您以其他方式询问: 为什么未定义的行为不会导致错误而不是给我们奇怪的行为 原因可能有很多。其中一个原因是性能。例如,在std::vector(至少在MSVC中)的实现中,没有检查在发布模式下索引是否超出范围。您可以尝试执行以下操作: #include <iostream> int main() { int *ptr = NULL; // It does not c

取消引用空指针是未定义的行为。未定义的行为不等于错误。如果触发未定义的行为,则可能发生任何情况。如果您以其他方式询问:

为什么未定义的行为不会导致错误而不是给我们奇怪的行为

原因可能有很多。其中一个原因是性能。例如,在
std::vector
(至少在MSVC中)的实现中,没有检查在发布模式下索引是否超出范围。您可以尝试执行以下操作:

 #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;
 }
这部分:
if(ptr==nullptr){throw;}
将减慢上下文中每个指针的解引用过程,这是不可取的

但是,可以这样做:

std::vector<int> v(4);
v[4]=0;
//Imaginary code
T& dereference(T* ptr){
    if(ptr==nullptr){
        throw;
    }
    return *ptr;
}

我想您现在明白了。

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


在第1点中,您对它不做任何操作,因此程序不必访问此指针描述的内存。这不会生成任何访问冲突错误。

在调试模式下编译,不进行优化,然后重试。.停止假设调用未定义的行为会导致已定义的行为。它不会。事实是,如果幸运的话,它会崩溃,并且您会失败ally想看看它来理解为什么这是真的。供你参考:-我们需要一个规范化的问题“为什么调用未定义行为的代码的行为方式会让我感到惊讶?”并回答“因为它可以”@WhozCraig以及编译器在这种情况下可以抛出一个没有副作用的未使用表达式的原因是因为取消引用NULL是UB。否则,表达式可能会有副作用。(这也是取消引用NULL是UB的原因。我们希望优化成为可能。)我将第二句话表述为“未定义的行为不等于崩溃”(这是一个错误-只是不一定是一个被捕获的错误).虽然你说的是真的,但我认为在这种特殊情况下,访问不会发生,因为它正在被优化。@MartinBonner嗯,我真的不知道。.错误,按定义,是不是有些不正确?至少应该被触发?我不是指被捕获,只是被触发?未定义的行为可能不会触发任何东西。对吗?是的,我认为nk所以..我一般回答..请随意用这个东西编辑答案,否则你可能会发布新的答案。你看不出为什么这被否决了。我认为这是完全正确的。@MartinBonner它没有解释为什么程序不需要访问内存。例如,如果取消引用空指针有一些已定义的行为,请通过removi进行优化拒绝访问将是非法的(因为你不会得到你应该得到的行为)。这是因为UB可以删除访问。@DavidSchwartz:这是错误的。访问可以优化掉,因为取消对非易失性的引用没有副作用。这与UB完全无关。如果代码是
int i=42,*ptr=&i;*ptr;
,编译器仍然可以优化掉access.@MartinBonner是的,因为它是UB。例如,如果取消引用NULL保证会导致崩溃,那么它会有副作用,崩溃,因此无法优化。因为取消引用NULL是UB,所以没有副作用。(同样,取消引用其他无效指针也是UB。)
//Imaginary code
T& dereference(T* ptr){
    #ifdef DEBUG
    if(ptr==nullptr){
        throw;
    }
    #endif
    return *ptr;
}