空 this 指针调用非虚成员函数可能不立即崩溃,但属未定义行为;一旦访问成员、虚函数或需对象地址的操作即触发段错误,虚函数调用必失败。

成员函数里访问 this 时,this 确实可以为空
只要不通过 this 访问成员变量或虚函数,空 this 不会立即崩溃。比如一个只做计算、不读成员的 const 成员函数,编译器可能允许调用:ptr->func() 中 ptr 为 nullptr,但 func 内没解引用 this,程序就“侥幸”跑过去了。
这不是标准保证的行为,而是取决于编译器是否生成了对 this 的实际使用。一旦函数体内出现 member_var、this->member_func()(非静态)、sizeof(*this) 或任何需要对象地址的操作,就会触发非法内存访问。
this 为空的典型触发场景
常见于裸指针误用,而非智能指针——因为后者通常带空检查或抛异常。典型路径包括:
- 手动
delete后未置nullptr,接着又调用成员函数 - 容器中存储原始指针,元素被析构后指针仍被误用
- C 风格接口回调传入
nullptr,C++ 包装层直接转成this - 模板元编程或 SFINAE 中,某些分支意外构造出空
this上下文(较罕见)
虚函数调用会让空 this 立刻失败
哪怕函数体是空的,只要声明为 virtual,调用时就必须通过 this 查虚表(vtable),而空指针解引用 vtable 地址必然段错误。例如:
立即学习“C++免费学习笔记(深入)”;
struct Base { virtual void f() {} };
Base* p = nullptr;
p->f(); // SIGSEGV,即使 f 什么也不做非虚函数则没有这层间接,所以风险延迟暴露——这也是空 this bug 难以复现和定位的原因之一。
底层机制:编译器怎么把普通函数变成“带 this”的成员函数?
成员函数本质上是编译器加了一个隐式首参:void func(Class* this, ...)。所有成员访问(如 data_)都被重写为 this->data_,再转成偏移量计算:*((char*)this + offsetof(Class, data_))。所以:
-
this是参数,不是语言内置“对象身份”,它可为任意值(包括nullptr) - 没有运行时检查,不类似 Java 的
NullPointerException自动抛出 - 内联、优化可能让
this在寄存器中消失,进一步掩盖空指针问题
真正危险的不是 this 为空,而是你忘了它只是个普通指针——它不会自动保护你避开野指针语义。











