Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

empty base class optimization

Tags:

c++

Two quotes from the C++ standard, §1.8:

An object is a region of storage.

Base class subobjects may have zero size.

I don't think a region of storage can be of size zero. That would mean that some base class subobjects aren't actually objects. How do these statements co-exist?

like image 215
fredoverflow Avatar asked May 13 '10 12:05

fredoverflow


2 Answers

A philosophical argument over the definition of "region" is unnecessary.

1.8/5 says, "Unless it is a bit-field, a most derived object shall have a non-zero size ... Base class sub-objects may have zero size".

So the standard is quite clear what objects (and hence what "regions of storage") can have zero size. If you disagree with the standard what "region" means in English that's one thing, you can fault the authors' (non-programming-related) literary skills. For that matter you can fault their poetic skills (14.7.3/7) But it's quite clear what the standard says here about the sizes of objects of class types.

The pragmatic way to read standards is that given two plausible interpretations of a word, choose the one which doesn't directly contradict another sentence in the same section of the standard. Don't choose the one which matches more closely your personal preferred use of the word, or even the most common use.

like image 178
Steve Jessop Avatar answered Oct 23 '22 20:10

Steve Jessop


C++ does not allow an object of size zero, because every object must have a unique memory address. So if you have:

struct empty {};

// ...

empty myempty;
empty* ptr = &myempty;

then ptr must be pointing to a unique memory address. The standard states the minimum size for an object is 1 byte for this purpose. Similarly, allocations of size 0 are allowed, and return a valid pointer, even if writing to that pointer is not allowed (this works for malloc(0), and new empty returns a pointer to one byte, since sizeof(empty) == 1).

If I derive from empty like so:

struct derived : public empty
{
    int data;
}

There is no longer any point in the base class empty occupying one byte, because all derived will have a unique address due to the data member. The quote "Base class subobjects may have zero size" is present to allow, in this case, for the compiler to not use any space for empty, such that sizeof(derived) == 4. As the title states, it's just an optimization, and it is perfectly legal for the empty part of derived to occupy zero space.

like image 31
AshleysBrain Avatar answered Oct 23 '22 20:10

AshleysBrain