When do programmers use Empty Base Optimization (EBO)

Solution 1:

EBO is important in the context of policy based design, where you generally inherit privately from multiple policy classes. If we take the example of a thread safety policy, one could imagine the pseudo-code :

class MTSafePolicy
{
public:
  void lock() { mutex_.lock(); }
  void unlock() { mutex_.unlock(); }

private:
  Mutex mutex_;
};

class MTUnsafePolicy
{
public:
  void lock() { /* no-op */ }
  void unlock() { /* no-op */ }
};

Given a policy based-design class such as :

template<class ThreadSafetyPolicy>
class Test : ThreadSafetyPolicy
{
  /* ... */
};

Using the class with a MTUnsafePolicy simply add no size overhead the class Test : it's a perfect example of don't pay for what you don't use.

Solution 2:

EBO isn't really an optimization (at least not one that you do in the code). The whole point is that an empty class has non-zero size, but when derived or deriving it can have zero size.

This is the most usual result:

class A { };
class B { };

class C { };
class D : C { };

#include <iostream>
using namespace std;

int main()
{
        cout << "sizeof(A) + sizeof(B) == " << sizeof(A)+sizeof(B) << endl;
        cout << "sizeof(D) == " << sizeof(D) << endl;

        return 0;
}

Output:

sizeof(A) + sizeof(B) == 2
sizeof(D) == 1

To the edit: The optimization is, that if you actually do derive (for example from a functor, or from a class that has only static members), the size of your class (that is deriving) won't increase by 1 (or more likely 4 or 8 due to padding bytes).

Solution 3:

The "Optimization" in the EBO means the case when you use base class can be optimized to use less memory than if you use a member of the same type. I.e. you compare

struct T : S 
{
      int x;
};

with

struct T
{
      S s;
      int x;
};

not with

struct T
{
      int x;
};

If your question is why would you have an empty class at all (either as a member, or as a base), it is because you use its member functions. Empty means it has no data member, not that it does not have any members at all. Things like this are often done when programming with templates, where the base class is sometimes "empty" (no data members) and sometimes not.

Solution 4:

Its used when programmers want to expose some data to client without increasing the client class size. The empty class can contain enums and typedefs or some defines which the client can use.The most judicious way to use such a class it it to,inherit such a class privately. This will hide the data from outside and wil not increase your class size.

Solution 5:

There can be empty classes which do not have any member variables, but member functions (static or non static) which can act as utility classes, lets call this EmptyClass. Now we can have a case where we want to create a class (let's call it SomeClass) which have a containment kind of relation with EmptyClass, but not 'is-a' relation. One way is to create a member object of type EmptyClass in SomeClass as follows:

class EmptyClass  
{
public:
    void someFun1();
    static int someUtilityFun2();
};
//sizeof(EmptyClass) = 1


class SomeClass
{
 private:
    EmptyClass e;
    int x;
};
//sizeof(SomeClass) = 8

Now due to some alignment requirements compilers may add padding to SomeClass and its size is now 8 bytes. The better solution is to have a SomeClass derive privately from EmptyClass and in this way SomeClass will have access to all member functions of EmptyClass and won't increase the extra size by padding.

class SomeClass : private EmptyClass
{
private:
    int x;
} 
//sizeof(SomeClass) = 4