C++ virtual function table memory cost

前端 未结 13 1728
抹茶落季
抹茶落季 2020-12-03 08:14

Consider:

class A
{
    public:
        virtual void update() = 0;
}

class B : public A
{
    public:
        void update() { /* stuff goes in here... */ }
         


        
相关标签:
13条回答
  • 2020-12-03 08:55

    Typically, every instance of a class with at least one virtual function will have an extra pointer stored with its explicit data members.

    There's no way round this, but remember that (again typically) each virtual function table is shared between all instances of the class, so there is no great overhead to having multiple virtual functions or extra levels of inheritance once you've paid the "vptr tax" (small cost of vtable pointer).

    For larger classes the overhead becomes much smaller as a percentage.

    If you want functionality that does something like what virtual functions do, you are going to have to pay for it in some way. Actually using native virtual functions may well be the cheapest option.

    0 讨论(0)
  • 2020-12-03 08:57

    If you're going to have millions of these things, and memory is a serious concern for you, then you probably ought not to make them objects. Just declare them as a struct or an array of 3 doubles (or whatever), and put the functions to manipulate the data somewhere else.

    If you really need the polymorphic behavior, you probably can't win, since the type information you'd have to store in your struct will end up taking up a similar amount of space...

    Is it likely that you'll have large groups of objects all of the same type? In that case, you could put the type information one level "up" from the individual "A" classes...

    Something like:

    class A_collection
    {
        public:
            virtual void update() = 0;
    }
    
    class B_collection : public A_collection
    {
        public:
            void update() { /* stuff goes in here... */ }
    
        private:
            vector<double[3]> points;
    }
    
    class C_collection { /* Same kind of thing as B_collection, but with different update function/data members */
    
    0 讨论(0)
  • 2020-12-03 08:59

    Moving away from the non issue of the vtable pointer in your object:

    Your code has other problems:

    A * array = new A[1000];
    array[0] = new B();
    array[1] = new C();
    

    The problem you are having is the slicing problem.
    You can not put an object of class B into a space the size reserved for an object of class A.
    You will just slice the B(or C) part of the object clean off leaving you with just the A part.

    What you want to do. Is have an array of A pointers so that it hold each item by pointer.

    A** array = new A*[1000];
    array[0]  = new B();
    array[1]  = new C();
    

    Now you have another problem of destruction. Ok. This could go on for ages.
    Short answer use boost:ptr_vector<>

    boost:ptr_vector<A>  array(1000);
    array[0] = new B();
    array[1] = new C();
    

    Never allocte array like that unless you have to (Its too Java Like to be useful).

    0 讨论(0)
  • 2020-12-03 09:03

    The space cost of a vtable is one pointer (modulo alignment). The table itself is not placed into each instance of the class.

    0 讨论(0)
  • 2020-12-03 09:05

    You have two options.

    1) Don't worry about it.

    2) Don't use virtual functions. However, not using virtual functions can just move the size into your code, as your code gets more complex.

    0 讨论(0)
  • 2020-12-03 09:05

    You're adding a single pointer to a vtable to each object - if you add several new virtual functions the size of each object will not increase. Note that even if you're on a 32-bit platform where pointers are 4 bytes, you're seeing the size of the object increase by 8 probably due to the overall alignment requirements of the structure (ie., you're getting 4 bytes of padding).

    So even if you made the class non-virtual, adding a single char member would likely add a full 8 bytes to the size of each object.

    I think that the only ways you'll be able to reduce the size of you objects would be to:

    • make them non-virtual (you you really need polymorphic behavior?)
    • use floats instead of double for one or more data members if you don't need the precision
    • if you're likely to see many objects with the same values for the data members, you might be able to save on memory space in exchange for some complexity in managing the objects by using the Flyweight design pattern
    0 讨论(0)
提交回复
热议问题