Quantcast
Channel: Visual C forum
Viewing all articles
Browse latest Browse all 15302

VC++ multiple inheritance empty base classes bloats object size

$
0
0

In previous versions/current versions of VC++ (including VC++2012), inheriting multiple base classes which are empty resulted in object size bloat, dependent on how many empty base classes there are.

For example, consider empty base classes (empty as in no non-static data members) Base1, Base2, Base3, ... BaseN

Then take a child class Child : Base1, Base2, Base3, ..., BaseN

In GCC/Clang, possibly other compilers the compiler recognizes these are empty base classes and will optimize the object size to be the size of Child's data members, plus some fixed object overhead. In some cases the overhead can bloat an object to 8, 12, 16, or more bytes (depends on how many base classes there are).

here's a quick working example:

#include <iostream>

template<size_t n>
class BaseN
{
};

class Child : BaseN<0>, BaseN<1>, BaseN<2>, BaseN<3>, BaseN<4>, BaseN<5>, BaseN<6>, BaseN<7>, BaseN<8>, BaseN<9>, BaseN<10>, BaseN<11>
{
	int c3;
};

int main(void)
{
	Child child;
	std::cout << "sizeof(Child): " << sizeof(child) << std::endl;
	return 0;
}

GCC4.8.1 outputs an object of size 4, while VC++2012 outputs 16.

This seems like a fairly obscure case, but Boost Operators defines binary operators in terms of op-assign operators:

class Point : addable<Point>, subtractable<Point>, multipliable<Point>, dividable<Point>, modable<Point>, incrementable<Point>, decrementable<Point>

For those unfamiliar with Boost Operators, to get around this by using a single inheritance chain. The internal implementations look something like:

template<typename T, typename B = empty_base>
struct addable : B
{
    friend T operator+(/*... some params in here*/)
    {
        // ... internal implementation
    }
    // ... may be multiple functions to cover various cases
}
Where a user could pass in a "base class" they wanted to inherit from, thus getting rid of multiple inheritance in favor of single inheritance chains, where VC++ can recognize these are all empty base classes and not impose any extra object overhead. empty_base is a dummy base class with nothing inside it.

This means a user would have to do something like this:

class point : addable<point, subtractable<point, multipliable<point, dividable<point> > > >

Or alternatively, they could instantiate these operator classes externally:

class point;

addable<point> paddable;
subtractable<point> psubtractable;

//...

From a readability standpoint, neither of these seem particularly optimal compared to the multiple inheritance define (IMO), and it gets worse if we have to deal with different lhs/rhs types (for example, multiplying a matrix by a scalar). Are the VC++ developers aware of this "issue" (I say "issue" because I understand it's not strictly required by the C++ standard, but is nice)? If so, are there plans to implement this optimization in the future?


Viewing all articles
Browse latest Browse all 15302

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>