5

比较以下两段代码:

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 机器。

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

4

5 回答 5

14

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

B *b;
b->val = 1;

所以当其中一个坠毁时你很幸运。

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

修复

您可以删除间接...

B b;
b.val = 1;

或者你可以分配它...

std::unique_ptr<B> b(new B());
b->val = 1;
于 2013-03-07T07:41:15.907 回答
4

您在此处取消引用未初始化的指针

b->val = 1;

指针指向的位置是不确定的:它可以指向任何地方。

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

真正发生的是,您正在向一段不应该写入的内存中写入值。没有办法知道那里有什么,而且 C++ 标准不能对可能的结果做出任何承诺。它只是调用这个 UB。避免这些情况取决于您。

于 2013-03-07T07:41:16.780 回答
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;
}
于 2013-03-07T07:42:36.170 回答
1

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

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

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

用标准术语来说,两个代码都表现出未定义的行为。这意味着几乎任何事情都可能发生,其中包括看似正常的工作(即,可能存在错误但没有明显的症状)。

于 2013-03-07T07:45:30.770 回答
0

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

于 2013-03-07T07:42:44.530 回答