c++ - 虚函数编译优化c++

标签 c++ function virtual

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

C++ 编译器能否并且会优化从进程函数调用 fnc 函数,考虑到它每次在循环内被调用时都是同一个函数? 还是每次调用函数时都从 vtable 中获取函数地址?

最佳答案

我检查了一个 example在 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();
}

和生成的汇编:

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

如您所见,它会在每次调用时读取 vtable。我猜这是因为编译器无法证明您没有在函数调用中更改 vtable(例如,如果您调用 placement new 或其他愚蠢的东西),因此从技术上讲,虚函数调用可能会在迭代之间发生变化。

关于c++ - 虚函数编译优化c++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43789996/

相关文章:

javascript - 将重复代码注入(inject)函数 : JavaScript

c# - c#中的virtual关键字

c++ - 从子类中调用父类(super class)

c++ - 在派生类中重新定义 typedef?

c++ - 如何构建 NS-3 以使用 C++0x/C++11 库?

c++ - 如何使用修饰键组合?

c++ - 如何访问 C++ 中链表中的对象

r - R中的第四角算法

c++ - 在派生类中专门化基类的模板化成员函数

perl - 使用 SOAP 和 Perl 调用带参数的函数