仮想継承のパフォーマンスへの影響はどうか調べた。以下は駄文
- test0
struct A { int a; virtual void x(){} }; struct B: virtual public A { int b; virtual void y(){} }; struct C: virtual public A { int c; virtual void z(){} }; struct D: public B, public C { int d; }; int main() { D d; D *pd = &d; for (int i = 0; i < 100000000; ++i) { pd->b += i; } return 0; }
- test1
struct A { int a; virtual void x(){} }; struct B: virtual public A { int b; virtual void y(){} }; struct C: virtual public A { int c; virtual void z(){} }; struct D: public B, public C { int d; }; int main() { D d; // D *pd = &d; for (int i = 0; i < 100000000; ++i) { d.b += i; } return 0; }
- test2
struct A { int a; virtual void x(){} }; struct B: public A { int b; virtual void y(){} }; struct C: public A { int c; virtual void z(){} }; struct D: public B, public C { int d; }; int main() { D d; D *pd = &d; for (int i = 0; i < 100000000; ++i) { pd->b += i; } return 0; }
実行時間は
- g++ -O0:
- test0 == test2 > test1
real 0m0.328s user 0m0.299s sys 0m0.003s real 0m0.252s user 0m0.250s sys 0m0.000s real 0m0.300s user 0m0.292s sys 0m0.003s
だった(複数回実行して適当に平均的なものをコピペした)。アセンブラを見た感じでは、test0とtest2ではオブジェクトの配置が異なるだけのように見えた。仮想継承を使用してもメンバへのアクセスにポインタを介する必要はないらしい。(仮想関数だとポインタを介してアクセスする)