有没有办法使用new
关键字在堆栈上分配(ala alloca
)而不是堆(malloc
)?
我知道我可以自己破解,但我不愿意。
答案 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();
}