2011-09-27 111 views
0

请检查此代码..C++奇怪的行为

class ex 
{ 
    int i; 
    public: 
    ex(int ii = 0):i(ii){} 
     ~ex(){cout<<"dest"<<endl;} 
    void show() 
    { 
     cout<<"show fun called"<<endl; 
    } 
}; 
int main(int argc , char *argv[]) 
{ 
    ex *ob = NULL; 
    ob->show(); 
     return 0; 
} 

当我们调用show方法会发生什么。

谢谢..

+2

这个问题的真正答案是没有人能够回答**究竟会发生什么**。 – Mahesh

+0

@Mahesh技术上说它会导致未定义的行为是答案。我们不知道这种未定义的行为是什么并不重要。换句话说,“未定义的行为”正是会发生的事情。 – sashang

+0

许多问题的另一个问题是[karthik](http://stackoverflow.com/users/644073/karthik)或[user692270](http://stackoverflow.com/users/692270/user692270)接受@karthik的答案。严重的是,你是否患有自卑感? –

回答

3
ex *ob = NULL; 
ob->show(); 

你提领一空指针导致不确定的行为。这不好。

如果不清楚解除引用的位置,则理解->运算符转换为 (*ob).show()

+0

大声笑,这得到了一个downvote - 小丑必须今天有效。 – sashang

+0

我没有downvote,但你的答案是不正确的。 show()函数可以是静态的:它不使用隐式的指针,所以没有什么不好的事情会发生。只有当函数试图访问成员变量时,调用对象的虚拟成员函数等,空指针才会被解除引用。 – TonJ

+0

@TonJ:'show()'不是静态的,可以在类定义中看到。 – DevSolar

0

行为未定义。程序的实际行为如何依赖于实现。我期望大多数实现尝试执行代码而不检查指针。所以你的第一个例子应该运行平稳,因为它没有引用该类的任何本地成员。

有趣的是,检查下面的代码做什么:

class ex 
{ 
    int i; 
    public: 
    ex(int ii = 0):i(ii){} 
    ~ex(){cout<<"dest"<<endl;} 
    virtual void show() 
    { 
     cout<<"show fun called"<<endl; 
    } 
}; 

int main(int argc , char *argv[]) 
{ 
    ex *ob = NULL; 
    ob->show(); 
    return 0; 
} 

如果该方法是虚拟的,也许在运行时需要访问对象的某些本地数据,导致空指针或错误的地址例外。

EDIT

我用GCC测试上的cygwin以下略作修改示例:

#include <iostream> 

using namespace std; 

class ex 
{ 
    int i; 
    public: 
    ex(int ii = 0):i(ii){} 
    ~ex(){cout<<"dest"<<endl;} 

    void show() 
    { 
     cout<<"show fun called"<<endl; 
    } 

    virtual void vshow() 
    { 
     cout<<"vshow fun called"<<endl; 
    } 
}; 

int main(int argc , char *argv[]) 
{ 
    ex *ob = NULL; 
    ob->show(); 
    ob->vshow(); 
    return 0; 
} 

,事实上,输出为:

show fun called 
Segmentation fault (Core dumped) 
+0

有没有这样的事情,作为空指针异常在C++ – sashang

+0

我并不是说C++运行时本身抛出异常,当您尝试解除引用NULL指针时,它由操作系统抛出。结果是程序崩溃。 – Giorgio

+0

当您引用无效内存时,操作系统执行的操作与操作系统有关。在linux上,生成一个SIGSEGV信号(http://en.wikipedia.org/wiki/SIGSEGV)并发送给程序,而不是空指针异常。你答案的原始措词是误导性的。 – sashang

1

调用show方法对由空指针指向的对象进行分类为“未定义行为”,这意味着无论发生什么事情不能说C++是错误的,因为错误在你身边。

未定义的行为意味着编译器编写者不需要关心错误编程的后果......所以他们可以自由地忽略这些情况。通常未定义的行为被认为意味着“崩溃”,但这与事实相去甚远。执行代码未定义行为可能崩溃,可以什么都不做,可以显然什么也不做,让你的程序崩溃以后在完美的罚款代替一个百万条指令或者它甚至可以在所有,但静默运行显然很好,没有崩溃破坏您的数据。

C++语言的一个主要假设是程序员没有犯错。在其他语言中,这不是真的,你会得到“运行时错误天使”,当你犯了一个错误时,它会检查和停止你的程序...在C++中,而不是那些检查被认为是太昂贵,因此,而不是“运行时错误天使” “未定义的行为守护进程”,如果出现错误,您将获得乐趣。我认为C++对初学者来说是一个非常不好的选择(初学者犯了很多错误),并且通过实验学习C++是不可能的(因为C++的后果)错误是非确定性的)。

在您的具体情况下,考虑到编译器编写者懒惰(对于程序员来说质量并不差),我猜测在x86架构上代码不会造成任何损害,并且可能会像指针一样执行对一个有效的对象。 这当然只是推测,因为它取决于编译器,硬件和编译器选项。可能有好的编译器有一个编译调试选项,它会生成崩溃的代码。

3

这是未定义的行为。

话虽这么说,在大多数编译器,你就可以,只要来调用空指针作为方法

1)他们不访问成员。

2)它们不是虚拟的。

大多数编译器将转化

ob->show() 

call ob::show 

,其存在于该应用程序空间内的有效方法。由于您没有访问会员,所以没有理由导致崩溃。

+0

应该提到“能够在大多数编译器上执行此操作”并不会改变它仍然是未定义行为的事实,即代码中的错误。 – DevSolar

+0

这是我的第一句话...... –

+1

......但其他人给人的印象是,这样做是有点好的,而且“没有理由让人崩溃”,这是恕我直言,这里给出的错误信息。这是不确定的行为,不要这样做,期限。 – DevSolar