Как разместить предметы в другом месте, кроме кучи? - PullRequest
0 голосов
/ 15 марта 2012

Можем ли мы разместить динамически размещенные объекты в каком-то другом месте, кроме кучи?Как мне определить перегруженный новый оператор для этого ??

Если у меня есть класс Arena, такой как

 class Arena{
      char area[2000];
 public:
      Arena(){}
 };

Arena my_arena (1000);

И я хочувыделить объекты из Arena my_arena ..

Кроме того, каковы возможные недостатки такого выделения памяти по сравнению с выделением из кучи производительности и т. д. ??

Ответы [ 3 ]

5 голосов
/ 15 марта 2012

Вы можете легко использовать новое место размещения для этого:

MyClass* p = new (area) MyClass;

Однако есть две проблемы, о которых вы должны знать:

  1. Нет гарантии, что `область`будет правильно выровнен для` MyClass`.Я обычно решаю это с помощью союза:
        union
        {
            double dummyForAlignment;
            //  Any other types which might be necessary...
            unsigned char area[2000];
        };
    
    Это очень специально;нет никаких формальных гарантий относительно того, какие типы вы должны добавить, чтобы быть уверенным.На практике вместо `double` я использую объединение большинства основных типов, плюс пару указателей, чтобы быть уверенным.
  2. Поскольку вы использовали new, компилятор не позаботится о вас, как об обычном элементе данных.Вам придется вызывать деструктор явно:
        p->~MyClass();
    
    Это означает, что вам придется отслеживать, сколько объектов какого типа и где было выделено.

Недостатками этой техники являются два момента, которые я только что упомянул.Кроме того, если вы не сохраните типизированный указатель на созданные объекты, у вас могут возникнуть проблемы с просмотром их в отладчике.Тем не менее, это полезный метод для некоторых конкретных целей: я использую его в своем классе Fallible, чтобы избежать необходимости использования конструктора по умолчанию;Стандартные контейнеры требуют этого, и, конечно же, стандартные классы вектора или массива обычно используют его также.Это также полезно для различных вариантов классов;Я предполагаю, что он используется, например, в boost::variant.

1 голос
/ 15 марта 2012

Возможно, но довольно низкого уровня.

Джеймс адекватно рассмотрел код C ++ 03, сделай сам, поэтому позвольте мне представить альтернативы.

Во-первых, в C ++ 03 у вас есть две альтернативы с Boost:

  • Boost.Optional : boost::optional<MyClass>, что, как следует из названия, позволяет иметь (или нет) экземпляр типа.
  • Boost.Variant : boost::variant<SomeClass,OtherClass,YetAnotherClass>, который является разновидностью union с безопасной семантикой типа и гарантированными вызовами конструкторов / деструкторов.

Во-вторых, в C ++ 11 была введена std::aligned_storage<Len,Align>, которая принимает два параметра:

  • необходимое количество байтов для хранения
  • Требуется выравнивание

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

Лично я бы выбрал boost::optional в вашем случае:

boost::optional<MyClass> Arena[256];

это моделирует именно то, что вы хотите, потому что по умолчанию boost::optional создается пусто .

0 голосов
/ 15 марта 2012

Вы можете просто сделать оператор перегрузки новым & delete и объявить переменные / класс в стеке.

Или, возможно, вы хотите использовать какой-то статический пул, чтобы вы могли управлять им статически.

...