новое в стеке, а не в куче (например, alloca vs malloc)

StackOverflow https://stackoverflow.com/questions/472015

  •  19-08-2019
  •  | 
  •  

Вопрос

Есть ли способ использовать new ключевое слово для выделения в стеке (аля alloca) вместо кучи (malloc) ?

Я знаю, что могу взломать свою собственную, но не хочу.

Это было полезно?

Решение

Чтобы разместить в стеке, либо объявите свой объект как локальную переменную по значению , либо вы можете фактически использовать alloca для получения указателя, а затем использовать оператор new на месте:

void *p = alloca(sizeof(Whatever));
new (p) Whatever(constructorArguments);

Однако, используя alloca и in-place, new гарантирует, что память освобождается при возврате, вы прекращаете автоматический вызов деструктора. Если вы просто пытаетесь обеспечить освобождение памяти при выходе из области действия, попробуйте использовать std::auto_ptr<T> или другой тип интеллектуального указателя.

Другие советы

Джеффри Хантин совершенно прав, что вы можете использовать новое размещение, чтобы создать его в стеке с помощью alloca. Но серьезно, почему ?! Вместо этого просто сделайте:

class C { /* ... */ };

void func() {
    C var;
    C *ptr = &var;

    // do whatever with ptr
}

Теперь у вас есть указатель на объект, размещенный в стеке. И он будет должным образом уничтожен, когда ваша функция существует.

Вы можете сделать:

Whatever* aWhatever = new ( alloca(sizeof(Whatever)) ) Whatever;

Я полагаю, вы могли бы использовать класс RAII для разрушения (EDIT:Также см этот другой ответ для получения дополнительной информации о потенциальных проблемах с этим подходом):

template <class TYPE>
class RAII
    {
    public:
        explicit RAII( TYPE* p ) : ptr(p) {}
        ~RAII() { ptr->~TYPE(); }
        TYPE& operator*() const { return *ptr; }
    private:
        TYPE* ptr;
    }

void example()
    {
    RAII<Whatever> ptr = new ( alloca(sizeof(Whatever)) ) Whatever;
    }

Вы можете использовать макрос, чтобы скрыть alloca.

С уважением Дэйвф

Будьте осторожны при использовании _alloca() с GCC

В GCC есть ошибка, которая делает <=> несовместимой с обработкой исключений SJLJ в C ++ (сообщается, что Dwarf2 работает правильно). Когда из функции, выделяющей память, выбрасывается исключение, ошибка приводит к повреждению стека до запуска деструкторов. Это означает, что любой класс RAII, работающий с выделенными объектами, должен запускаться в другой функции для правильной работы. Правильный способ сделать это выглядит так:

void AllocateAndDoSomething()
{
  Foo* pFoo = reinterpret_cast<Foo*>(_alloca(sizeof(Foo)));
  new (pFoo) Foo;

  // WARNING: This will not work correctly!
  // ScopedDestructor autoDestroy(pFoo);
  // pFoo->DoSomething();

  // Instead, do like this:
  DoSomething(pFoo);
}

void DoSomething(Foo* pFoo)
{
  // Here, destruction will take place in a different call frame, where problems
  // with _alloca() automatic management do not occur.
  ScopedDestructor autoDestroy(pFoo);
  pFoo->DoSomething();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top