16

キーワードを使用して、ヒープ()の代わりにnewスタック(ala)に割り当てる方法はありますか?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;
    }

マクロを使用して alloca を非表示にすることができます。

よろしく DaveF

于 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 に答える