The size of any object or member subobject is required to be at least 1 even if the type is an empty class
type (that is, a class
or struct
that has no non-static data members), in order to be able to guarantee that the addresses of distinct objects of the same type are always distinct.
However, base class
subobjects are not so constrained, and can be completely optimized out from the object layout:
#include <cassert>
struct Base {}; // empty class
struct Derived1 : Base {
int i;
};
int main() {
// the size of any object of empty class type is at least 1
assert(sizeof(Base) == 1);
// empty base optimization applies
assert(sizeof(Derived1) == sizeof(int));
}
Empty base optimization is commonly used by allocator-aware standard library classes (std::vector
, std::function
, std::shared_ptr
, etc) to avoid occupying any additional storage for its allocator member if the allocator is stateless. This is achieved by storing one of the required data members (e.g., begin
, end
, or capacity
pointer for the vector
).
Reference: cppreference