为何未通过new关键字实例化的类指针执行delete后仍能成功调用成员函数?
为什么这段代码能"成功"调用
f()? 这问题其实戳中了C++里成员函数调用的底层逻辑,还有未定义行为的特殊性,咱们一步步拆解:
1. 非虚成员函数的调用不依赖对象的实际内存
先看你的f()函数:它是非虚成员函数,而且里面完全没有访问类的成员变量——只是输出一个固定字符串。
在C++里,非虚成员函数是静态绑定的,编译器在编译阶段就确定了函数的调用地址。当你写b->f()时,编译器会偷偷把它转换成类似A::f(b)的形式:把指针b作为隐式的this参数传递给f()。
因为f()根本没用到this指针(不需要读取对象内存),所以哪怕b是个野指针,函数也能正常执行——它只是跑一段固定的代码而已,和b指向的内存有没有效没关系。
2. 关于delete b的行为
首先,A* b;这行只声明了指针,没初始化,所以b是个野指针,指向内存里的随机地址。
对野指针执行delete是标准定义的未定义行为——这意味着什么都可能发生:可能立刻崩溃,可能啥反应都没有,甚至可能悄悄破坏其他内存数据。你的代码里delete b后没崩,纯粹是运气好(或者说倒霉,因为这种未定义行为会埋下巨大隐患),但这绝对不是合法操作。
3. 这绝对不是正确的代码!
虽然你的代码看起来"运行成功"了,但完全是依赖未定义行为的巧合。如果给A加个成员变量,让f()访问它:
class A{ private: int x = 10; public: void f(){cout<<"f, x="<<x;} };
再运行b->f()大概率会直接崩溃——因为此时函数需要通过this指针读取x,而this是野指针,指向的内存完全无效。
另外,未初始化指针、随意delete野指针都是极度危险的操作,实际项目里必须彻底避免——它们会导致难以排查的内存错误、程序崩溃甚至安全问题。
内容的提问来源于stack exchange,提问作者Sachin Palande
相关产品推荐
相关产品推荐

