两个几乎完全相同的C ++程序,一个运行良好但另一个运行时出错

时间:2013-03-07 07:39:30

标签: c++ class pointers runtime-error

比较以下两段代码:

1

#include <iostream>
using namespace std;
class B{
public:
    int val;
};
int main(){
    B *b;
    int t = 0;
    b->val = 1;
    cout << 123 << endl;
    return 0;
}

2

#include <iostream>
using namespace std;
class B{
public:
    int val;
};
int main(){
    B *b;
    b->val = 1;
    cout << 123 << endl;
    return 0;
}

两个版本都编译。代码#1运行良好,但代码#2运行错误。

我正在使用C ++ 11编译并运行Windows机器。

这让我很困惑。谁能告诉我原因?

5 个答案:

答案 0 :(得分:14)

两者都错了。 b指针未初始化,因此您不应通过它访问内存。

B *b;
b->val = 1;

当其中一人坠毁时,你很幸运。

另一个你运气不好,并没有崩溃。

修复

您可以删除间接...

B b;
b.val = 1;

或者你可以分配它......

std::unique_ptr<B> b(new B());
b->val = 1;

答案 1 :(得分:4)

您在这里取消引用未初始化的指针

b->val = 1;

指针指向的位置未确定:它可能指向任何位置。

在此指针之后是未定义的行为(UB),这意味着任何事情都可能发生,这就是您所看到的。

真正发生的是你正在为一段你不应该写的内存写一个值。没有办法知道那里有什么,而且C ++标准对可能的结果没有任何承诺。它只是称这个UB。你应该避免这些情况。

答案 2 :(得分:1)

您需要在使用之前初始化任何指针。 你看到的是所谓的未定义行为。

#include <iostream>
using namespace std;
class B{
public:
    int val;
};
int main(){
    B *b = new B();
    int t = 0;
    b->val = 1;
    cout << 123 << endl;
    delete b;
    return 0;
}

应该和

一样好用
#include <iostream>
using namespace std;
class B{
public:
    int val;
};
int main(){
    B b;
    int t = 0;
    b.val = 1;
    cout << 123 << endl;
    return 0;
}

答案 3 :(得分:1)

问题是您使用的是未初始化的指针B* b;。在C和C ++中,内置类型在创建时不会被初始化:它们只是持有垃圾。

解决问题的方法很简单:不要使用指针。 B b;将创建一个类实例并调用其构造函数。

  

代码#1运行良好,但代码#2运行错误。

在Standardese的说法中,两个代码都显示未定义的行为。这意味着几乎任何事情都可能发生,并且包含看似正常工作(即,可能存在错误,但没有明显的症状)。

答案 4 :(得分:0)

b->val指向无效的内存位置。在分配b

之前,为b->val分配内存