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 从共享库加载实例只是一个例子,排除内联函数的可能性。
即使这样做:
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)