this是编译器隐式传递的首个参数,x86 windows下通过ecx寄存器传递,linux/macos下按system v abi作为第1参数入rdi,x64 windows下入rcx;operator new为静态函数,无this。

成员函数调用时,this 是怎么进来的?
它不是靠你写出来的参数,而是编译器悄悄塞进第一个隐式参数位置的。不同平台和 ABI 下,传参方式略有差异,但核心逻辑一致:就像 C 函数调用一样,this 被当作一个额外的指针参数,在调用前就准备好,走的是和普通参数相同的寄存器或栈路径。
thiscall 在 x86 Windows 上到底干了什么?
这是微软 MSVC 在 32 位 x86 下对非静态成员函数的默认调用约定。它的关键行为是:this 走 ECX 寄存器,其余参数从右往左压栈。
- 如果你手写汇编或逆向看反汇编,会发现
mov ecx, [some_obj]总在call前出现 - 返回值、栈平衡规则和
__cdecl类似(调用者清栈),但this不占栈空间 - 注意:MSVC 在 x64 下统一用
__fastcall变体(this进RCX),thiscall已被弃用,仅保留在 x86 文档里 - g++/clang 在 x86 Linux 下不认
thiscall,它们用的是 System V ABI:所有参数(含this)都按规则进寄存器或栈,this就是第一个参数
为什么重载 operator new 时不能直接访问 this?
因为 operator new 是静态成员函数,它在对象内存分配完成前就被调用 —— 此时对象还没构造,this 根本不存在。
- 错误写法:
void* operator new(size_t s) { return this->malloc(s); }→ 编译不过,this未定义 - 正确做法:它只能访问全局
malloc、静态变量或传入的s,返回的是原始内存地址 - 真正拿到
this是在后续的构造函数里,此时内存已分配,对象生命周期才开始
内联汇编或 ABI 兼容时,this 的位置容易搞错吗?
非常容易。尤其当你手动写汇编包装成员函数,或跨语言绑定(比如用 rust 调 c++ 成员函数)时,漏掉 this 或放错位置会导致段错误或随机崩溃。
立即学习“C++免费学习笔记(深入)”;
- x86-64 System V(Linux/macOS):
this是第 1 个参数,进RDI;int a, int b分别进RSI、RDX - x86-64 microsoft(Windows):
this是第 1 个参数,进RCX;其余依次是RDX、R8、R9 - 如果用
extern "C"暴露成员函数,必须自己把this当成显式参数传进去,否则 ABI 不匹配 - 调试时可查
objdump -d或用gdb看call前寄存器状态,确认RCX/RDI是否已被设为对象地址
最常被忽略的一点:成员函数指针不是普通函数指针,它可能包含偏移、调整值甚至虚表索引 —— 所以你不能简单假设 this 就是“第一个参数”,尤其在涉及多重继承或虚继承时,编译器会在调用前悄悄修正它。