new 在堆栈而不是堆上(如 alloca 与 malloc)
Posted
技术标签:
【中文标题】new 在堆栈而不是堆上(如 alloca 与 malloc)【英文标题】:new on stack instead of heap (like alloca vs malloc) 【发布时间】:2010-10-03 02:08:04 【问题描述】:有没有办法使用new
关键字在堆栈(ala alloca
)而不是堆(malloc
)上分配?
我知道我可以自己破解,但我不想这样做。
【问题讨论】:
【参考方案1】:你可以这样做:
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。
问候 戴夫F
【讨论】:
【参考方案2】:在 GCC 中使用 _alloca()
时要小心
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();
【讨论】:
【参考方案3】:Jeffrey Hantin 非常正确,您可以使用placement new 在alloca 的堆栈上创建它。但是,说真的,为什么?相反,只需这样做:
class C /* ... */ ;
void func()
C var;
C *ptr = &var;
// do whatever with ptr
您现在有一个指向堆栈上分配的对象的指针。而且,当你的函数存在时,它会被正确地销毁。
【讨论】:
您的示例正是我将其声明为按值的局部变量的意思。 注意:如果你已经定义了一个非空的构造函数,该类必须在 cpp 中定义一个空的构造函数。 我的用例 - 比如说C
在子类 C1
和 C2
中覆盖了 virtual
方法。那我可能想做C * ptr = criteria ? new (alloca(sizeof(C1))) C1(...) : new (alloca(sizeof(C2))) C2(...);
【参考方案4】:
要在堆栈上分配,要么将你的对象声明为局部变量按值,或者你可以实际使用 alloca 来获取指针,然后使用就地 new 运算符:
void *p = alloca(sizeof(Whatever));
new (p) Whatever(constructorArguments);
但是,虽然使用 alloca 和 in-place new 可确保在返回时释放内存,但您放弃了自动析构函数调用。如果您只是想确保在退出作用域时释放内存,请考虑使用std::auto_ptr<T>
或其他一些智能指针类型。
【讨论】:
以上是关于new 在堆栈而不是堆上(如 alloca 与 malloc)的主要内容,如果未能解决你的问题,请参考以下文章