针对同一对象上重复调用同一函数的虚函数优化

Ian*_*nas 4 c++ virtual-functions vtable compiler-optimization

假设有这样一个抽象类:

class Base {
   public:

   virtual void f() = 0;

   virtual ~Base()  = default;
};
Run Code Online (Sandbox Code Playgroud)

还有一些功能:

void function (Base& x, bool flag1, bool flag2, bool flag3) {

   if(flag1)
      x.f();
   if(flag2)
      x.f();
   if(flag3)
      x.f();
}
Run Code Online (Sandbox Code Playgroud)

main()函数中,我从共享库加载派生自该类的实例:

int main() {
  Base* x = /* load from shared lib*/;

  bool flag1 = getchar() == '1';
  bool flag2 = getchar() == '2';
  bool flag3 = getchar() == '3';

  function(*x, flag1, flag2, flag3);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

问题:我是否可以期望在一次函数调用中,void function (Base& x, bool flag1, bool flag2, bool flag3)即使所有三个标志都是 ,虚拟函数表也只会被访问一次true?也就是说,编译器是否可以只在表中找到该函数一次并在另外两次使用其地址?

Ps 从共享库加载实例只是一个例子,排除内联函数的可能性。

Sol*_*cko 5

即使这样做:

void function (Base& x, bool flag1, bool flag2, bool flag3) {
   if(flag1 || flag2 || flag3) {
      if(flag1)
         x.f();
      if(flag2)
         x.f();
      if(flag3)
         x.f();
   }
}
Run Code Online (Sandbox Code Playgroud)

mov rax, QWORD PTR [rbx]使用 GCC -O3为每次调用加载 vtable 指针 ( ) :

function(Base&, bool, bool, bool):
        push    r12
        mov     r12d, ecx
        push    rbp
        mov     ebp, edx
        push    rbx
        mov     rbx, rdi
        test    sil, sil
        jne     .L2
        test    dl, dl
        jne     .L2
.L6:
        test    r12b, r12b
        jne     .L12
.L9:
        pop     rbx
        pop     rbp
        pop     r12
        ret
.L2:
        mov     rax, QWORD PTR [rbx]
        mov     rdx, QWORD PTR [rax]
        test    sil, sil
        je      .L7
        mov     rdi, rbx
        call    rdx
        test    bpl, bpl
        je      .L6
        mov     rax, QWORD PTR [rbx]
.L7:
        mov     rdi, rbx
        call    [QWORD PTR [rax]]
        test    r12b, r12b
        je      .L9
.L12:
        mov     rax, QWORD PTR [rbx]
        mov     rdi, rbx
        pop     rbx
        pop     rbp
        pop     r12
        mov     rax, QWORD PTR [rax]
        jmp     rax
Run Code Online (Sandbox Code Playgroud)