Question

I have some classes (most of them are abstract, with virtual inheritance):

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

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

class MyA : virtual public A{
    public:
        virtual void f1(){ ... }
        virtual void f2(){ ... }
};

class MyB : virtual public B, virtual public MyA{
    public:
        void f3(){ ... }
};

Now I use them:

B * object = new MyB();
object->f1(); //declared in A, imp. in MyA
object->f3(); //declared in B, imp. in MyB

Everything works fine, and the code is "good" for me (I can fast switch from MyB to YourB with changes in 1 line only).

But my question is:

How much additional memory it uses, compared to the similar code listed below (same result, different structure)?

I'm not good with memory layouts/vTables, so please explain it to me in a simple way - I want to know, if my application will spend more resources (memory) and if the executable will be slower?

And I compare that code to that one:

class MyA{
    public:
        virtual void f1(){ ... }
        virtual void f2(){ ... }
};

class MyB : public MyA{
    public:
        void f3(){ ... }
};

MyB * object = new MyB();
object->f1(); //declared in MyA, imp. in MyA
object->f3(); //declared in MyB, imp. in MyB

The sizeof(object) returns 4 in both examples (Win x32, Visual Studio native compiler), but I'm not sure if it's authoritative here. Maybe it doesn't count something - I don't think that both samples are 100% equal.

Was it helpful?

Solution

It depends on the implementation, but typically virtual inheritance will need:

  • an extra pointer (or offset) for each virtual base class: the adjustment to convert (for example) B* to A* will depend on which other subobjects in the same object also derive virtually from A. I think this can be stored in the vtable, rather than the object itself, so that the overhead could be per-class rather than per-object.
  • extra logic in the constructor and destructor, to determine whether or not the virtual base object needs initialising/destroying at that point.
  • extra work for some pointer conversions, reading the stored pointer/offset rather than applying a compile-time constant.

For memory usage, you can measure the per-object overhead in your implementation by printing sizeof (MyB). Any per-class overhead will probably be negligible, unless you have a huge number of classes.

OTHER TIPS

Before I start, your concern is known as a premature optimization. There are other concerns to worry about before size and space: correctness and robustness.

Inheritance is usually implement through Virtual Function Tables, in essence, a table of addresses to functions. So the amount of extra code space depends on the quantity of virtual functions.

Virtual functions are executed using a jump table. A common practice is to load the Program Counter with the value in the Function Table. This is usually 2 assembly instructions.

The amount of variable space for the function table may be less than the memory wasted by alignment padding in a structure. The wasted execution time is less than the overhead to call a function.

Edit 1:
BTW, assembly instructions are usually executed in 1 microsecond or less. So calling through a function table would take 2 microseconds. Compare this with waiting for disk I/O or User I/O.

This is why it is a premature optimization: optimizing before profiling. Profile the entire code and attend to the bottlenecks before worrying about this waste of code and variable space.

For commonly used compilers, the overhead will be roughly as following

  1. Memory Overhead: extra pointer to vtable for each parent class.
  2. Runtime Overhead: each virtual method call will have indirections to find the right implementation of the method for actual type of the invoking object.

sizeof(object) returns 4 in both case because you are measuring size of pointer to object, not object itself. Pointer size is same no matter to which object it points.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top