在 C++ 中,函数调用约定决定了函数参数和返回值的传递方式。现代约定包括传值(按值传递)和传引用(按引用传递)。常见的调用约定类型包括 cdecl、stdcall、fastcall 和 aapcs。传引用通常更有效率,因为它避免了不必要的拷贝。
C++ 函数调用约定的前世今生
在 C++ 中,函数调用约定决定了函数参数和返回值是如何在调用者和被调用者之间传递的。本文将深入探讨函数调用约定,从历史上发展到现代实践。
历史起源
最初,C 语言没有显式的调用约定,这导致不同编译器之间的不兼容。为了解决这个问题,引入了 System V ABI(应用程序二进制接口),它指定了 x86 架构上的调用约定。
现代约定
现代调用约定通常分为两类:
C++ 支持通过引用或指针传递参数。对于大对象或可能被修改的参数,传引用通常更有效率,因为它避免了不必要的拷贝。
调用约定类型
传统的 x86 调用约定 (cdecl)
Microsoft x86 调用约定 (stdcall)
eax
寄存器返回。x64 调用约定 (fastcall)
rcx
, rdx
, r8
, r9
寄存器传递。ARM64 调用约定 (aapcs)
x0
到 x7
寄存器传递。实战案例
考虑以下函数,它在传值的情况下交换两个整数:
void swap(int a, int b) { int tmp = a; a = b; b = tmp; }
如果使用传引用的调用约定,可以简化函数:
void swap(int& a, int& b) { int tmp = a; a = b; b = tmp; }
在传引用时,a
和 b
是指向原始值的引用,因此上面的交换操作可以修改原始值。