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

问题描述 投票:0回答:3

假设有这样一个抽象类:

class Base {
   public:

   virtual void f() = 0;

   virtual ~Base()  = default;
};

还有一些功能:

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

   if(flag1)
      x.f();
   if(flag2)
      x.f();
   if(flag3)
      x.f();
}

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;
}

问题:我是否可以期望在一次函数调用中

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

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

c++ compiler-optimization virtual-functions vtable
3个回答
0
投票

一般来说,你不能保证编译器会优化虚函数表查找只发生一次。依赖特定的编译器优化性能关键代码通常不是一个好主意。作为一个简单的解决方法,也许你可以这样做:

if (flag1 || flag2 || flag3) {
    x.f();
}

但是我不知道你用这三个标志的目的或意义。


0
投票

在 C 和 C++ 中有 AS IF 规则,因此编译器可以进行您期望的优化(如果启用)。问题是您没有保证编译器会这样做。要查看它是否发生,您必须检查汇编输出,这不是很好。


0
投票

即使这样做:

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();
   }
}

使用 GCC -O3 为每次调用加载 vtable 指针(

mov rax, QWORD PTR [rbx]

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
© www.soinside.com 2019 - 2024. All rights reserved.