#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;
}
在上面的代码中,当我评论&#34; Point-2&#34;代码没有崩溃。 但是,当我取消评论&#34; Point-2&#34;它崩溃了。 由于ptr理想情况下为NULL,因此Point-1也应该崩溃。如果我错了,请纠正我。 有人可以解释一下为什么代码没有崩溃当我简单地解除指针?
答案 0 :(得分:2)
取消引用空指针是未定义的行为。未定义的行为不等于错误。如果触发未定义的行为,可能会发生任何事情。如果你问另一种方式:
为什么未定义的行为不会导致错误而不是给我们奇怪的行为?
可能是由于很多原因。一个原因是表现。例如,在std::vector
的实现中(至少在MSVC中),在发布模式下不检查索引是否超出范围。您可以尝试这样做:
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;
}
我想你现在明白了。
答案 1 :(得分:0)
在第2点,您尝试显示0x0地址的内容,这会产生访问冲突错误。
在第1点中,您不执行任何操作,因此程序不必访问此指针所描述的内存。这不会产生访问冲突错误。