Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I think your question is good - in fact, some of the earlier articles about the empty base class optimization talk about the "empty member optimization" and specifically say that a similar optimization could apply to members. Maybe, before there was a standard, some compilers did this.</p> <p>This is just idle speculation, I don't have much to back it up, but I had a look at some of these areas of the standard yesterday.</p> <h2>C compatibility</h2> <p>In this example:</p> <pre><code>struct X{}; struct Y{}; struct Z { struct X x; struct Y y; int i; }; </code></pre> <p><strike><code>Z</code> would be a POD under C++03 rules, but would not be layout-compatible with C if <code>x</code> and <code>y</code> were zero-sized subobjects. C layout compatibility is one of the reasons for the existence of PODs. This problem can't happen with base classes because C doesn't have base classes, and classes with base classes aren't PODs in C++03, so all bets are off :).</strike>Visitor has noted that C doesn't support empty structs, in fact. So this entire argument is wrong. I'd just assumed that it did - it seemed like a harmless generalization.</p> <p>Further, programs seem to assume things, like that <code>y</code> has a greater address than <code>x</code>, and stuff like that - this is guaranteed by the relational operators on pointers in 5.10/2. I don't really know if there's a compelling reason to allow this, or how many programs use it in practice.</p> <p><strike>IMO, this is the strongest argument of all of these.</strike></p> <h2>Doesn't generalize well to arrays</h2> <p>Continuing the above example, add this:</p> <pre><code>struct Z1 { struct X x[1]; struct Y y[1]; int i; }; </code></pre> <p>...one might expect that <code>sizeof(Z1) == sizeof(Z)</code>, and that <code>x</code> and <code>y</code> also work as normal arrays do (i.e. that you can form a past-the-end pointer, and that pointer is different to any element's address). One of these expectations would be broken with zero-sized subobjects.</p> <h2>Less compelling than the base case</h2> <p>One of the main reasons for deriving from an empty base is because it's a policy or interface type class. These are often empty, and requiring them to take up space would impose an "abstraction penalty", i.e. make better organized code more bloated. This is something that Stroustrup doesn't want in C++ - he wants appropriate abstraction for minimal runtime cost.</p> <p>On the other hand, if you declare a member of a type, you don't inherit its functions, typedefs, etc; and you don't get the special pointer conversions from derived to base, so perhaps there's less reason to have a zero-sized member than a zero-sized base.</p> <p>A counterexample here is something like the Allocator policy class in STL containers - you don't necessarily want your containers to derive from it, but you want to "keep it around" without it taking up overhead.</p> <h2>Empty base class case covers most uses</h2> <p>...you can use private inheritance instead of declaring a member if you're worried about the space overhead. It's not quite as direct, but you can more or less achieve the same thing. Obviously this doesn't work so well if you've got lots of empty members that you would like to take up zero space.</p> <h2>It's another special case</h2> <p>There are quite a few subtle things that don't work with this optimization. For example, you can't <code>memcpy</code> the bits of a zero-sized POD subobject into a <code>char</code> array, and then back, or between zero-sized subobjects. I've seen people implement <code>operator=</code> using <code>memcpy</code> (I don't know why...) which would break this sort of thing. Presumably it's less of a problem to break such things for base classes instead of members.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload