Когда программисты используют Оптимизацию пустых баз (EBO) - PullRequest
19 голосов
/ 01 декабря 2010

Я читал об Оптимизации пустой базы (EBO).Во время чтения у меня возникли следующие вопросы:

  1. Какой смысл использовать пустой класс в качестве базового класса, когда ничего не вносит в производные классы (ни функциональность, нимудрый, ни в отношении данных) ?

  2. В этой статье , я прочитал это:

// S пустструктура класса T: S{int x;};

[...]

Обратите внимание, что мы не потеряли ни данных, ни точности кода: при создании автономного объекта типа S размер объекта по-прежнему равен 1 (илибольше) как прежде;только когда S используется в качестве базового класса другого класса, его объем памяти уменьшается до нуля.Чтобы понять влияние этого сохранения, представьте вектор, который содержит 125 000 объектов. Один EBO экономит половину мегабайта памяти!

Означает ли это, что если мы не используем "S" в качестве базового класса "T", мы бы обязательно потреблять вдвое больше мегабайта памяти?Я думаю, в статье сравниваются два разных сценария, которые я не считаю корректными.

Я хотел бы знать реальный сценарий, когда EBO может оказаться полезным. (То есть, в том же сценарии мы бы обязательно быть в убытке, если мы не используем EBO!).

Обратите внимание, что если ваш ответ содержит объяснения, подобные этому:

Весь смысл в том, что пустоекласс имеет ненулевой размер, но при выводе или выводе он может иметь нулевой размер, тогда я НЕ спрашиваю об этом, поскольку я это уже знаю.У меня вопрос: зачем вообще выводить свой класс из пустого класса? Даже если он не выводит и просто пишет свой класс (без какой-либо пустой базы), он теряется каким-либо образом?

Ответы [ 8 ]

34 голосов
/ 01 декабря 2010

EBO важен в контексте проектирования на основе политики , где вы обычно наследуете в частном порядке от нескольких классов политики.Если мы возьмем пример политики безопасности потоков, можно представить псевдокод:

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 */ }
};

С учетом класса разработки на основе политики, такого как:

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

Использование классас MTUnsafePolicy просто не увеличивайте размер над классом Test: это прекрасный пример не платите за то, что вы не используете .

6 голосов
/ 01 декабря 2010

EBO на самом деле не оптимизация (по крайней мере, не та, которую вы делаете в коде). Все дело в том, что пустой класс имеет ненулевой размер, но при выводе или выводе он может иметь нулевой размер.

Это самый обычный результат:

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;
}

Выход:

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

Для редактирования: Оптимизация заключается в том, что если вы действительно производите (например, от функтора или от класса, который имеет только статические члены), размер вашего класса (который является производным) не увеличится на 1 (или, скорее всего, на 4 8 из-за байтов заполнения).

5 голосов
/ 01 декабря 2010

«Оптимизация» в EBO означает, что при использовании базового класса можно оптимизировать использование меньшего объема памяти, чем при использовании члена того же типа. То есть ты сравни

struct T : S 
{
      int x;
};

с

struct T
{
      S s;
      int x;
};

не с

struct T
{
      int x;
};

Если ваш вопрос заключается в том, зачем вам вообще иметь пустой класс (либо в качестве члена, либо в качестве базы), то это потому, что вы используете его функции-члены. Пустой означает, что у него нет элемента данных, а не то, что у него нет элементов вообще. Подобные вещи часто выполняются при программировании с использованием шаблонов, где базовый класс иногда «пуст» (без элементов данных), а иногда нет.

4 голосов
/ 23 октября 2012

Используется, когда программисты хотят предоставить клиенту некоторые данные без увеличения размера клиентского класса. Пустой класс может содержать перечисления и typedefs или некоторые определения, которые может использовать клиент. Наиболее разумный способ использовать такой класс - наследовать такой класс конфиденциально. Это позволит скрыть данные извне и не увеличит размер вашего класса.

1 голос
/ 01 декабря 2010

EASTL дает хорошее объяснение того, зачем им нужен EBO, также подробно объясняется в статье, на которую они ссылаются / credit

0 голосов
/ 01 декабря 2010

Основное преимущество, о котором я могу думать, это dynamic_cast. Вы можете взять указатель на S и попытаться выполнить динамическое вещание на все, что унаследовано от S, при условии, что S предлагает виртуальную функцию, подобную виртуальному деструктору, что он в значительной степени должен выполнять в качестве базового класса. Например, если вы реализуете язык с динамической типизацией, вы можете пожелать, чтобы каждый тип производился от базового класса исключительно для целей хранения с удаленным типом и проверки типов с помощью dynamic_cast.

0 голосов
/ 01 декабря 2010

В большинстве случаев пустой базовый класс используется либо полиморфно (о чем упоминается в статье), либо как классы «тегов», либо как классы исключений (хотя обычно они создаются из std :: exception, который не является пустым) , Иногда есть веская причина разработать иерархию классов, которая начинается с пустого базового класса.

Boost.CompressedPair использует EBO для уменьшения размера объектов в случае, если один из элементов пуст.

0 голосов
/ 01 декабря 2010

EBO - это не то, на что влияет программист, и / или программист был бы наказан за то, что он (а) решил не наследовать от пустого базового класса.

class X : emptyBase { int X; };
class Y { int x };

вы получаете sizeof(X) == sizeof(Y) или нет.Если вы это сделаете, компилятор реализует EBO, если нет, то нет.

Никогда не бывает ситуаций, когда sizeof(Y) > sizeof(X) произойдет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...