在学校,我们关于virtualC++中的函数,以及如何在执行时而不是编译时解决(或找到或匹配,我不知道术语是什么 - 我们不是用英语学习).老师还告诉我们,编译时分辨率比执行时间快得多(并且它是有意义的).但是,快速实验会暗示其他情况.我已经建立了这个小程序:
#include <iostream>
#include <limits.h>
using namespace std;
class A {
public:
void f() {
// do nothing
}
};
class B: public A {
public:
void f() {
// do nothing
}
};
int main() {
unsigned int i;
A *a = new B;
for (i=0; i < UINT_MAX; i++) a->f();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我编写了上面的程序并命名了它normal.然后,我修改A为这样:
class A {
public:
virtual void f() {
// do nothing
}
};
Run Code Online (Sandbox Code Playgroud)
编译并命名virtual.这是我的结果:
[felix@the-machine C]$ time ./normal
real 0m25.834s
user 0m25.742s
sys 0m0.000s
[felix@the-machine C]$ time ./virtual
real 0m24.630s
user 0m24.472s
sys 0m0.003s
[felix@the-machine C]$ time ./normal
real 0m25.860s
user 0m25.735s
sys 0m0.007s
[felix@the-machine C]$ time ./virtual
real 0m24.514s
user 0m24.475s
sys 0m0.000s
[felix@the-machine C]$ time ./normal
real 0m26.022s
user 0m25.795s
sys 0m0.013s
[felix@the-machine C]$ time ./virtual
real 0m24.503s
user 0m24.468s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
似乎有一个稳定的~1秒的差异有利于虚拟版本.为什么是这样?
相关与否:双核奔腾@ 2.80Ghz,两次测试之间没有额外的应用程序运行.Archlinux与gcc 4.5.0.正常编译,如:
$ g++ test.cpp -o normal
Run Code Online (Sandbox Code Playgroud)
此外,-Wall也不会吐出任何警告.
编辑:我把我的程序分成了A.cpp,B.cpp和main.cpp.此外,我使f()(两个A::f()和B::f())函数实际上做了一些事情(x = 0 - x其中x是一个public int成员A,初始化为1 A::A()).将其编译为六个版本,这是我的最终结果:
[felix@the-machine poo]$ time ./normal-unoptimized
real 0m31.172s
user 0m30.621s
sys 0m0.033s
[felix@the-machine poo]$ time ./normal-O2
real 0m2.417s
user 0m2.363s
sys 0m0.007s
[felix@the-machine poo]$ time ./normal-O3
real 0m2.495s
user 0m2.447s
sys 0m0.000s
[felix@the-machine poo]$ time ./virtual-unoptimized
real 0m32.386s
user 0m32.111s
sys 0m0.010s
[felix@the-machine poo]$ time ./virtual-O2
real 0m26.875s
user 0m26.668s
sys 0m0.003s
[felix@the-machine poo]$ time ./virtual-O3
real 0m26.905s
user 0m26.645s
sys 0m0.017s
Run Code Online (Sandbox Code Playgroud)
虚拟时,未经优化的速度仍然快1秒,我觉得有点奇怪.但这是一个很好的实验,并感谢你们所有人的答案!
小智 11
一旦vtable在缓存中,实际执行某些操作的虚拟和非虚拟函数之间的性能差异非常小.在使用C++开发软件时,您通常不应该关注自己.正如其他人所指出的那样,在C++中对未经优化的代码进行基准测试是毫无意义的.
分析未经优化的代码几乎毫无意义.使用-O2产生有意义的结果.使用-O3甚至会导致更快的代码,但除非你编译它可能不会产生一个现实的结果A::f,并B::f分别对main(即,在不同的编译单元).
根据反馈,甚至-O2可能过于激进.2 ms的结果是因为编译器完全优化了循环.直接电话不是那么快; 事实上,应该很难观察到任何明显的差异.将实现移动f到单独的编译单元以获取实数.定义类在.h,但定义A::f和B::f在自己的.cc文件.