C++中未初始化指针调用成员函数为何未报错反而执行了?


#include <iostream>
using namespace std;
class BBB {
public:
    void print() {
        cout << "1234" << endl;
    }
};


class InitPtrClass {
public:
    void init_ptr() {};
    void use_ptr() {
        if (bbb == nullptr) {
            cout << "s" << endl;
        }
        bbb->print();
    };
private:
    BBB *bbb = nullptr;
};

int main()
{
    InitPtrClass ipc;
    ipc.use_ptr();
    return 0;
}

为什么这段代码会打印出1234,编译运行,不应该报错么?

如题

阅读 792
avatarAI BotBETA

在你的代码中,实际上存在一个明显的逻辑错误,该错误导致未初始化的指针 bbb 被错误地解引用并调用了其成员函数 print(),但你的代码实际上包含了一个检查 bbb 是否为 nullptr 的条件语句,这个条件语句应该阻止未初始化指针的解引用。然而,由于条件语句的位置和代码逻辑,这个检查实际上并没有阻止 print() 函数的调用。

这里是问题所在:

void use_ptr() {
    if (bbb == nullptr) {
        cout << "s" << endl;
    }
    bbb->print(); // 这行代码无条件执行,不依赖于前面的if语句
};

use_ptr() 函数中,你首先检查 bbb 是否为 nullptr,并在是的情况下打印 "s"。然而,无论 bbb 是否为 nullptr,接下来的 bbb->print(); 都会执行。这意味着如果 bbbnullptrbbb->print(); 仍然会尝试解引用一个空指针,这通常会导致运行时错误(如段错误或访问违规)。

然而,在你的代码中,由于 bbb 已经在类中初始化为 nullptr,并且没有其他代码在 use_ptr() 调用之前修改 bbb 的值,理论上它应该打印 "s" 并随后崩溃(或者在某些编译器/运行环境下表现为未定义行为,可能包括不崩溃并错误地执行了 print(),但这实际上是一个错误或异常行为)。

为什么你看到了 "1234" 而不是崩溃?

有几种可能的原因,但最常见的是你的代码在运行时环境或编译器中有某种异常或未定义行为的表现。例如,内存可能已经被分配并初始化为某种状态,使得 bbb->print(); 实际上调用了一个有效的 print() 方法(尽管这是一个非常罕见和危险的情况)。然而,更可能的是,你的代码或测试环境中有一些未显示的部分(如其他函数或全局变量)影响了 bbb 的值,或者你的测试环境以某种方式掩盖了崩溃。

如何修复?

你应该将 bbb->print(); 放在 if 语句的 else 部分,以确保在 bbb 不是 nullptr 时才调用它:

void use_ptr() {
    if (bbb == nullptr) {
        cout << "s" << endl;
    } else {
        bbb->print();
    }
};

这样,如果 bbbnullptr,则不会尝试解引用它,从而避免运行时错误。

2 个回答

这是 未定义行为 。

未定义行为并不是一定会崩溃,而是什么都可能发生。具体会发生啥跟编译器/编译选项/体系结构...都有关系。

新手上路,请多包涵

有个地方不符合C++的语义规则。
InitPtrClass类中的bbb指针被初始化为nullptr,在use_ptr()函数中,您没有先检查指针是否为空就进行了解引用就调用了它的成员函数print()

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏