16

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

我知道我可以自己破解,但我不想这样做。

4

4 回答 4

23

要在堆栈上分配,要么通过 value将您的对象声明为局部变量,或者您可以实际使用 alloca 获取指针,然后使用就地 new 运算符:

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

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

于 2009-01-23T05:58:05.790 回答
12

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

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

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

    // do whatever with ptr
}

您现在有一个指向堆栈上分配的对象的指针。而且,当您的功能存在时,它将被正确地销毁。

于 2009-01-23T06:11:05.903 回答
6

你可以这样做:

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

您可以使用 RAII 类进行我认为的破坏(编辑:另请参阅此其他答案以获取有关此方法的潜在问题的更多信息):

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

您可以使用宏来隐藏分配。

问候戴夫夫

于 2009-01-23T11:06:59.147 回答
2

_alloca()与 GCC 一起使用时要小心

GCC 有一个错误,它与 C++ 中_alloca()的 SJLJ 异常处理不兼容(据报道 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();
}
于 2009-10-24T10:35:47.640 回答