Igo*_*vic 5 c++ virtual function
class Base
{
public:
virtual void fnc(size_t nm)
{
// do some work here
}
void process()
{
for(size_t i = 0; i < 1000; i++)
{
fnc(i);
}
}
}
Run Code Online (Sandbox Code Playgroud)
考虑到每次在循环内被调用时,c ++编译器都将是同一个函数,因此c ++编译器能否并且是否将从进程功能中优化对fnc函数的调用?还是每次调用该函数都会从vtable获取函数地址?
我在 godbolt.org 上查看了一个示例。结果是不,没有一个编译器优化它。
这是测试源:
class Base
{
public:
// made it pure virtual to decrease clutter
virtual void fnc(int nm) =0;
void process()
{
for(int i = 0; i < 1000; i++)
{
fnc(i);
}
}
};
void test(Base* b ) {
return b->process();
}
Run Code Online (Sandbox Code Playgroud)
和生成的asm:
test(Base*):
push rbp ; setup function call
push rbx
mov rbp, rdi ; Base* rbp
xor ebx, ebx ; int ebx=0;
sub rsp, 8 ; advance stack ptr
.L2:
mov rax, QWORD PTR [rbp+0] ; read 8 bytes from our Base*
; rax now contains vtable ptr
mov esi, ebx ; int parameter for fnc
add ebx, 1 ; i++
mov rdi, rbp ; (Base*) this parameter for fnc
call [QWORD PTR [rax]] ; read vtable and call fnc
cmp ebx, 1000 ; back to the top of the loop
jne .L2
add rsp, 8 ; reset stack ptr and return
pop rbx
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它在每次调用时都会读取 vtable。我猜这是因为编译器无法证明您没有更改函数调用内的虚函数表(例如,如果您调用新的放置或一些愚蠢的东西),因此,从技术上讲,虚拟函数调用可能会在迭代之间发生变化。
| 归档时间: |
|
| 查看次数: |
752 次 |
| 最近记录: |