虚拟功能需要多少字节的额外内存?

时间:2013-01-23 06:33:32

标签: c++ memory virtual-functions

从虚拟函数的简单到复杂结构有各种各样的情况。什么因素决定了它所需的额外内存数量?例如

class A            {virtual void F() {}   };
class B : public A {virtual void F() {}   };

A和B需要多少内存才能与没有虚函数的类进行比较?另一个有2个虚函数的例子,

class A            {virtual void F() {}   virtual void G() {}   };
class B : public A {virtual void F() {}   virtual void G() {}   };

和示例3

class A            {virtual void F() {};   virtual void G() {}  };
class B : public A {virtual void F() {}                         }; 

[---------------添加更多有趣的问题------------------]

  1. 每个虚方法都有虚拟方法表吗?如果是这样,我认为对于一个类(不是对象,对吧?我认为VPTR是静态的。),有许多虚方法需要一些VPTR,每个VPTR都用于虚方法。右

  2. 是否可以为所有虚拟方法只构建一个表,并且只在一个类中放置一个VPTR?

  3. 我认为虚拟功能的调用速度应该比手动ifs更快,因为使用了直接的VPTR。右

  4. [--------------- A Test ----------------]

    我做了一个测试,并用VS2010和intel c ++编译器显示我的结果。

    struct A
    {
        static int s_i;
        int i;
        virtual void F()    {i+=1;}
        virtual void G()    {i+=2;}
    };
    
    struct B
        : public A
    {
        int j;
        virtual void F()    {i+=3;}
        virtual void G()    {i+=4;}
    
        virtual void H()    {i+=5;}
    };
    
    struct C
        : public B
    {
        virtual void F()    {i+=6;}
    
        virtual void H()    {i+=7;}
    };
    
    TEST(MemoryForVirtualMethod)
    {
        CHECK_EQUAL(sizeof(A), 8);
        CHECK_EQUAL(sizeof(B), 12);
        CHECK_EQUAL(sizeof(C), 12);
    }
    

    从结果来看,我的结论是

    (1)对于具有虚函数的每个对象,添加一个(隐藏指针)VPTR。

    (2)对于每个类,为该类的所有虚拟方法构建虚拟方法表。

    (3)将VPTR置于对象中是为了实现动态调度,因为引用的类可能不是动态类。

    (4)实现调用效率高(比手动ifs快)但牺牲了一些内存。

    非常感谢!

1 个答案:

答案 0 :(得分:3)

由于虚拟函数通常实现为virtual method table (vtable),因此我猜测每个O(number of virtual functions) classobject一个额外指针。不是你想要的那么精确,但应该给出一个粗略的想法。 正如@AlokSave所提到的那样,还有许多其他细微之处,它们都是特定于编译器的,可能不够一致,无法估计。

  

通常,编译器为每个类创建一个单独的vtable。创建对象时,会将指向此vtable的指针(称为虚拟表指针,vpointer或VPTR)添加为此对象的隐藏成员

来源:Wikipedia

你覆盖的函数数量(如你的例子中所示)是(我猜测)无关紧要,除非在编译时可以安全地确定要调用的函数,在这种情况下可能是在第二个例子中被视为静态调度函数(G())。这也取决于编译器。

  

编译器通常避免在编译时解析调用时使用vtable。

最后,虚拟功能的成本可能比内存更难。