堆栈而不是堆的新东西(比如alloca vs malloc)

时间:2009-01-23 05:49:23

标签: c++ stack new-operator

有没有办法使用new关键字在堆栈上分配(ala alloca)而不是堆(malloc)?

我知道我可以自己破解,但我不愿意。

4 个答案:

答案 0 :(得分:23)

要在堆栈上分配,要么将对象声明为本地变量按值,要么实际上可以使用alloca获取指针然后使用就地新运算符:

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

但是,使用alloca和in-new时确保在返回时释放内存,您放弃自动析构函数调用。如果您只是想确保在退出作用域时释放内存,请考虑使用std::auto_ptr<T>或其他一些智能指针类型。

答案 1 :(得分:12)

Jeffrey Hantin非常正确,您可以使用placement new在堆栈上使用alloca创建它。但是,说真的,为什么?!相反,只需:

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

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

    // do whatever with ptr
}

现在您有一个指向堆栈上分配的对象的指针。并且,当你的函数存在时,它将被正确销毁。

答案 2 :(得分:5)

你可以这样做:

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

你可以使用RAII类进行我想的破坏(编辑:另见this other answer for more information on potential problems with this approach):

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。

此致 DaveF

答案 3 :(得分:2)

_alloca()与GCC

一起使用时要小心

GCC在C ++中有bug which makes _alloca() incompatible with SJLJ exception handling(据报道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();
}