首页 > 解决方案 > 回调函数中的参数顺序

问题描述

我正在观看此 C++Con 演讲https://www.youtube.com/watch?v=e8SyxB3_mnw&t=2933s&ab_channel=CppCon ,其中给出了类似以下代码的内容(https://godbolt.org/z/av4Tbn):

struct Handler {
  void handle(int x, int y, int z);

  static void callback0(void *instance, int x, int y, int z) {
    static_cast<Handler *>(instance)->handle(x, y, z);
  }

  static void callback1(int x, int y, int z, void *instance) {
    static_cast<Handler *>(instance)->handle(x, y, z);
  }
};

auto c0 = Handler::callback0;
auto c1 = Handler::callback1;

该代码生成以下程序集:

Handler::callback0(void*, int, int, int):
        jmp     Handler::handle(int, int, int)
Handler::callback1(int, int, int, void*):
        mov     r8d, edi
        mov     rdi, rcx
        mov     ecx, edx
        mov     edx, esi
        mov     esi, r8d
        jmp     Handler::handle(int, int, int)
c1:
        .quad   Handler::callback1(int, int, int, void*)
c0:
        .quad   Handler::callback0(void*, int, int, int)

显然,回调 0 是这里的首选版本,但我不明白回调 1 中“幕后”发生了什么?有人可以详细说明吗?

标签: c++event-handling

解决方案


callback0()中,参数是通过 CPU 寄存器以handle()期望它们的确切顺序传递的,其中instance变为handlerthis指针,因此无需重新排列任何值,因此为什么要单独jmp使用。

callback1中,参数必须重新排列到handle()期望它们的正确 CPU 寄存器中,jmp然后才能调用。

这与在各种调用约定中传递参数的工作方式有关。


推荐阅读