C ++虚函数执行效率

时间:2010-01-09 04:21:45

标签: c++ function virtual

我正在努力更好地了解虚拟功能的性能 这是一个示例代码:

struct Foo {
    virtual void function1();
    virtual void function2() { function1(); }
};

struct Bar : Foo {
    virtual void function1();
}

Bar b;
Foo &f = b;

b.function2();
b.function1();
f.function2();

对于代码示例的最后三行中的三个调用中的每一个,是否所有这些调用都必须在虚拟表中查找函数指针?必须为f对象执行多少次查找。曾经可以被编译器内联?

感谢

6 个答案:

答案 0 :(得分:7)

对b的调用是静态的 - 编译器在编译时肯定知道b在运行时的类型(显然是Bar),因此它将直接使用将被调用的方法的地址。

虚拟仅在通过指针/引用进行调用时很重要,因为调用在运行时可能具有不同的目标。例如,如果您在指针上调用function1并且在运行时更改了指针指向的实际类型,则这很重要。

现在这里你在f上调用function2的情况很棘手有两个原因:函数永远不会被覆盖,并且你使用了一个无法重新赋值的引用。因此,一个真正智能的编译器可以看到所有输入文件可以100%放心地确定调用的目标是什么(因为你不打算在已编译的代码中添加新类)。但是,AFAIK,编译器不必这样做,所以你会付出代价。

一般来说,如果您不打算永远覆盖某个功能,请不要将其设为虚拟。

答案 1 :(得分:5)

Elan Ruskin在这个主题上做了一个基准:

http://assemblyrequired.crashworks.org/2009/01/19/how-slow-are-virtual-functions-really/

当然,你可以决定他的结果对你的实践是如何的: - )

答案 2 :(得分:0)

这是你可以尝试的东西。将这三个函数调用包含在具有一百万次迭代的for循环中。然后通过分析器运行程序,以了解成本差异。如果运行linux,callgrind(profiler)和kcachegrind(可视化结果)将为您提供出色的洞察力,甚至可以直到汇编代码级别。

答案 3 :(得分:0)

In C++, To achieve run-time polymorphism 2 things are required:
1. Function must be a member of the class and declared as virtual.
2. Use Pointers or references to make dynamic function dispatch possible.

e.g.
   Derived d;
   Base &refBase = d;
   Base *pBase = d;

   d.foo();
   // resolved at compile time based on the static type of object (Derived)

   refBase.foo();  //will resolve at runtime
/* Here refBase is reference to Base class , but its dynamic type reference to 
Derived class object so its referring to derived class object and accordingly derived  class function is called (using look up in vtbl) and similarly for pointers.
*/

 So in your case first 2 function calls are resolved at compiler time since invoked by
 object rather than pointers or references .

 The last call will be resolved at run-time by making  lookup in vtable of derived class. 

答案 4 :(得分:0)

对方法的实际调用大约需要两倍的虚拟方法。要记住的是,内联不会带来任何结果。如果你可以在第一时间接听电话,那么你通常也可以使用虚拟电话,当你不是时,你可以经常将它内联。特别要记住,通话时间不会影响运行的实际代码。

答案 5 :(得分:0)

These days, the performance implications完全可以忽略不计。即使在游戏或其他性能密集型代码中也是如此。