2012-04-23 18 views
0

私の知る限り(あるいは、少なくとも私のコンパイラで:gccと打ち鳴らす)、次のコードは許可されている:それは非常にきれいにすることができますので、フォースの暗黙の呼び出し

struct BLA { void *operator new(std::size_t size, int i1, int i2); }; 

int main(void) 
{ 
    struct BLA *bla = new (3,5) BLA; 
    return 0; 
} 

イマオが、これは非常にクールです記憶域を割り当てる構文。
この手法では、オブジェクトを非常にクリーンな方法で割り当て、コンストラクタを不正に使用する必要がない方法を表す変数を渡すことができます。
残念ながら、C++標準では、(AFAIK)と同様の方法で 'delete'演算子は機能しないと言います。すなわち:

struct BLA 
{ 
    void *operator new(std::size_t size, int i1, int i2); 
    void operator delete(void *p, int i1, int i2); 
}; 

int main(void) 
{ 
    struct BLA *bla = new (3,5) BLA; 
    delete (3,5) bla; 
    return 0; 
} 

は、「削除」行にハードエラーが発生します。
この非標準の暗黙的な呼び出しを許可する方法(多分コンパイラスイッチ)はありますか?
BLA :: operator delete(bla、3、5)?上記の行を使用して

が本当に素敵な構文:(

+0

* "多分コンパイラスイッチ" * - 標準以外のものを求めているときは、使用しているコンパイラを言及する価値があります。個人的には、私はそれが痛みの価値があるようになるような何かを考えていない! – Flexo

+0

私はgccとclangを使っています。個人的に私はスイッチを通過する際の痛みは見られませんが) – iolo

+1

申し訳ありませんが、私は見たときにそこになかったことを誓ったことができました。痛みはスイッチを通過することではなく、それがコミットしたとき(大きなコードベース)に、突然別のコンパイラに切り替えて*すべて*を書き直さなければならなくなります。勝利はそれほど大きくありません(コンストラクタ/デストラクタではできませんし、動機によってはテンプレートのトリッキーなこともあります)。あなたは意図的に異なるものである懸念(メモリの割り当てとメモリの初期化)を混在させています。 – Flexo

答えて

2

を破壊するであろうdelete演算子への引数を渡す方法はありません。このhereためBjarneの推論を見た。アンは、そのようなあなたが実装された1つがあるとして削除し、オーバーロード明示的に呼び出された場合、または対応する新しいスローが行われた場合にのみ使用されます。

正しい削除が呼び出されるようにする必要がある場合は、使用できるトリックがあります。コンストラクタは、必要以上に64ビットを確保し、オブジェクトの前にこれらの2つのパラメータを配置します(返す前にオフセットされた位置を返すだけです)ポインタ)。オブジェクトを削除するときは、パラメータを渡すのではなく、オブジェクトの前からフェッチし、それらを使用して正しく割り当てを解除します。こうすることで、パラメータなしでdeleteを使うことができ、各オブジェクトが正しく割り当て解除されることを確認できます。

わからない、次はあなたのシステムのバグと考えられる場合:

struct BLA *bla = new (3,5) BLA; 
delete (4,6) bla; 

すなわち、割り当て以外の割り振り解除が可能な場合、このメソッドは機能しません。割り当てを解除するのが危険な場合、この方法よりも明示的にパラメータを保存する方が、実際にははるかに安全です。

+0

問題は、私がそれをする方法が見つからないということではありません。私はちょうど考えていた: "ねえ、私はその構文を使用したい"。しかし、それが不可能だと言うなら、私はあなたを信じます。私はこれにはあまり期待していなかった;) – iolo

+0

+1、いくつかの余分なメモリを割り当てる前に、あなたが本当にthsiのような何かをしなければならない場合に行く方法です – Flexo

+0

ちょうど覚えておいてくださいより大きな型のアライメントの制約を壊さない。 –

2

Stroustrupは、C++で 'placement delete'の欠如について議論するのにsomething that's probably helpfulを挙げています。

削除をカスタマイズするのではなく、独自の破棄機能を作成できます。

struct BLA { 
    void *operator new(std::size_t size, int i1, int i2); 
    void destroy(int i1, int i2); 
private: 
    ~BLA(); // private so you can't call regular delete 
}; 

void BLA::destroy(int i1, int i2) { 
    this->~BLA(); // explicit destructor call 
    // your custom deallocation code 
} 

FWIW - あなたは新しいに渡されたものをそのマッチを削除するには、パラメータを渡すために持つことは行うには非常に危険なことのように思えます。少し余分なスペースを割り当てて、i1i2を保存することをお勧めします。そして、あなたのdestroy関数は、パラメータを全く必要とすべきではありません。

関連する問題