C++が新しい配置に直接対応する配置削除を行わないのはなぜですか?つまり、デストラクタを呼び出し、適切な配置削除演算子を呼び出しますか?
例えば:
MyType *p = new(arena) MyType;
...
//current technique
p->~MyType();
operator delete(p, arena);
//proposed technique
delete(arena) p;
_operator delete
_は、動的にディスパッチされる非メンバー関数または静的メンバー関数であるという点で独特です。仮想デストラクタを持つタイプは、最も派生したデストラクタから独自のdelete
への呼び出しを実行します。
_struct abc {
virtual ~abc() = 0;
};
struct d : abc {
operator delete() { std::cout << "goodbye\n"; }
};
int main() {
abc *p = new d;
delete p;
}
_
( この例を実行 。)
これが配置削除で機能するためには、デストラクタはどういうわけか追加の引数を_operator delete
_に渡す必要があります。
operator delete
_オーバーロードが必要です。operator delete
_を呼び出すかを指定します。しかし、デストラクタがルックアップを行う場合、これは、#1と同じ複数の仮想関数定義を必要とするという問題にぶつかります。ある種の抽象的なオーバーロードセットを作成する必要があり、それを呼び出し元が解決します。あなたには完全に良い点があります、そしてそれは言語への素晴らしい追加になるでしょう。理論的には、それをdelete
の既存のセマンティクスに後付けすることもおそらく可能です。ただし、ほとんどの場合、delete
の全機能を使用するわけではなく、疑似デストラクタ呼び出しの後にarena.release(p)
のようなものを使用するだけで十分です。
すでにptr->~type();
があるので、そうする必要はありません。
おそらく、割り当て解除なしでデストラクタを明示的に呼び出すための構文がありましたが(あなたの質問とまったく同じように)、生のメモリで明示的に構築するための構文はありませんでしたか?
実際には、コンストラクターが例外をスローした場合に、placementnewを使用して「割り当てられた」オブジェクトの実装によって呼び出される配置削除があります。
プレースメント削除関数は、プレースメントの新しい式から呼び出されます。特に、オブジェクトのコンストラクターが例外をスローした場合に呼び出されます。このような状況では、プログラムでメモリリークが発生しないようにするために、配置削除関数が呼び出されます。
新しい配置の全体的なポイントは、オブジェクトの作成をそのメモリ管理から分離することです。したがって、オブジェクトの破壊中にそれを結び付けることは意味がありません。
オブジェクトのメモリがヒープからのものであり、オブジェクトとそのメモリの有効期間を同じにしたい場合は、operator new
とoperator delete
を使用します。特別な動作が必要な場合は、それらをオーバーライドします。
[。