# this 指针的原理
面试官问"this 指针是什么",大多数人能答出"指向当前对象的指针"。但追问"this 存在哪里""编译器怎么传递 this""const 成员函数里 this 是什么类型""this 能为空吗"就容易卡住了。关键是理解 this 不是什么神秘的东西——它就是编译器自动传入的第一个参数。
# 简要回答
this 是编译器隐式传给每个非静态成员函数的第一个参数,类型是 T* const(指针本身不可变,指向的对象可变)。调用 obj.func(x) 时,编译器实际生成的是 func(&obj, x),把对象地址作为第一个实参传入。this 通常通过寄存器传递(x86 用 ecx,即 thiscall 约定),不占栈空间。const 成员函数中 this 类型变为 const T* const,所以不能修改成员。静态成员函数没有 this,因为它不绑定任何对象实例。
# 详细回答
编译器的转换——this 的本质
C++ 的成员函数调用在编译后和普通函数没有区别。编译器把 obj.func(a, b) 转换成类似 func(&obj, a, b) 的形式,对象地址作为隐含的第一个参数传入,这个参数就是 this。所以 this 不是存储在对象里的,也不是什么特殊的运行时机制——它就是一个函数参数。
this 的类型
普通成员函数中,this 的类型是 T* const:指针本身是常量(不能让 this 指向别的对象),但指向的对象不是常量(可以修改成员)。const 成员函数中,this 变成 const T* const:指针本身不可变,指向的对象也不可变,所以不能通过 this 修改任何非 mutable 成员。
this 的存储位置
this 是函数参数,具体存在哪取决于调用约定。x86 平台的 thiscall 约定中,this 通过 ecx 寄存器传递,不占栈空间。x64 和 ARM 平台也通常用寄存器传递前几个参数。只有在函数内部需要取 this 的地址时,编译器才会把它溢出到栈上。
静态成员函数为什么没有 this
静态成员函数属于类而不属于任何对象实例,调用时不需要对象(T::staticFunc()),编译器不会传入对象地址,所以没有 this。这也是静态函数不能访问非静态成员的根本原因——没有对象地址,无法定位成员的内存位置。

# 知识拓展
Q:return *this 是什么意思?
解引用 this 得到当前对象本身(类型是 T&),返回它就是返回对象的引用。链式调用 obj.set(1).set(2).set(3) 就是靠每个方法 return *this 实现的——每次返回的都是同一个对象的引用,所以可以继续调用它的方法。
Q:this 能为 nullptr 吗?
语法上可以构造出来(((T*)nullptr)->func()),但这是未定义行为。如果 func 内部不访问任何成员变量,某些编译器下可能不崩溃,但这纯属巧合,不能依赖。任何通过空 this 访问成员的操作都会段错误。
Q:this 和智能指针有什么关系?
this 是裸指针,不管理生命周期。如果需要在对象内部获取指向自身的 shared_ptr,不能直接 shared_ptr<T>(this)(会导致双重释放),必须继承 std::enable_shared_from_this<T>,然后调用 shared_from_this()。
Q:为什么不能在构造函数里调用虚函数并期望多态?
构造函数执行时,对象的动态类型还是当前正在构造的类(vptr 指向当前类的 vtable),this 的静态类型也是当前类。所以即使调用虚函数,也只会调到当前类的版本,不会调到派生类的重写版本。
评论
验证登录状态...