有趣的C ++代码片段,有什么解释吗?

时间:2010-09-23 15:45:19

标签: c++ null

  

可能重复:
  Why am I able to make a function call using an invalid class pointer

class B
{
    public:
    int i;
    B():i(0){}
    void func1()
    {
        cout<<“func1::B\n”;
    }
    void func2()
    {
        cout<<“i = “<<i;
    } 
};


int main()
{

    B *bp = new B;

    bp->func1();

    delete bp;

    bp = NULL;

    bp->func1();
    bp->func2();

    return 1; 
}

输出:

func1::B 
func1::B 
Runtime Exception:
NULL pointer access

7 个答案:

答案 0 :(得分:7)

这是NULL(或无效)对象指针的旧故事;对于标准,在NULL对象指针上调用方法会导致未定义的行为,这意味着,就标准而言,它可以完美地工作,它可能会炸毁计算机或杀死一些随机的人

这里发生的是C ++编译器典型的类实现的结果:类通常实际上只包含字段的结构,所有方法实际上都是将this指针作为隐藏参数的函数

现在,在这种实现中,如果您使用NULL this指针调用方法,如果它不访问任何字段,则实际上不会取消引用this ,所以它应该运行正常(与func1)一样。

相反,如果该方法尝试访问任何字段(例如func2),它将取消引用this指针,NULL将导致崩溃(取消引用NULL指针,同样是未定义的行为,但通常会导致崩溃)。

请注意,如果您调用的方法是虚拟的,则几乎可以肯定使用NULL this指针调用它们会导致崩溃,因为虚拟调用是通过vtable解析的(一个函数指针数组),它隐藏在类的开头。

顺便说一句,void main()不是标准的;它应该是int main()argvargc是可选的。)

答案 1 :(得分:5)

当代码被修复为编译时,结果是合理预期的。

func1()没有引用该类的任何成员,因此它没有发现它有一个空指针可以作为this使用; func2()确实引用this->i,因此this为空时失败。

严格来说,这是未定义的行为 - 任何事情都可能发生。但核心转储或运行时异常是对该特定错误的最常见响应之一。

答案 2 :(得分:1)

有什么好处的?第一个输出是正确的。第二个未定义的行为。第三种是尝试访问现在不存在的类中包含的信息。程序正确识别它是一个NULL指针。

答案 3 :(得分:0)

不是专家意见,只是看着这个:

bp-&gt; func1()不需要对类成员的任何访问 - 在Java中,这最好定义为静态。也许编译器正在内联函数?

答案 4 :(得分:0)

您正在删除bp,然后尝试从中调用,因为那里没有对象,实际上您已将引用设为null,因此存在运行时异常。

以这种方式思考:

你告诉编译器任何实例都不需要空间,因此当它尝试使用变量'i'时,它没有存储在任何有意义的地方并且程序失败。因为你已经将引用设为null,所以程序会在它执行此操作之前就将其捕获。

答案 5 :(得分:0)

我认为严格来说,第二次调用bp-&gt; func1()应该已经崩溃,但是通过输出它仍然使用已分配的bp调用(但现在是NULL),也许是一些错误的编译器优化(?) 。然后在bp-&gt; func1()调用内部它真的崩溃,因为成员i不可访问。

答案 6 :(得分:0)

从使用删除后使用指针的位置开始,输入“undefined behavior”land

因此,除此之外的任何行为都依赖于编译器实现,即使它“看起来有效”,也必须被认为是错误的。