web-dev-qa-db-ja.com

C ++に配置削除式がないのはなぜですか?

C++が新しい配置に直接対応する配置削除を行わないのはなぜですか?つまり、デストラクタを呼び出し、適切な配置削除演算子を呼び出しますか?

例えば:

MyType *p = new(arena) MyType;
...
//current technique
p->~MyType();
operator delete(p, arena);

//proposed technique
delete(arena) p;
32
user283145

_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_に渡す必要があります。

  • 解決策1:仮想関数を介して引数を渡します。これには、静的メンバーごとに個別の仮想デストラクタと、異なる引数を使用したグローバル_operator delete_オーバーロードが必要です。
  • 解決策2:仮想デストラクタが呼び出し元への関数ポインタを返し、どの_operator delete_を呼び出すかを指定します。しかし、デストラクタがルックアップを行う場合、これは、#1と同じ複数の仮想関数定義を必要とするという問題にぶつかります。ある種の抽象的なオーバーロードセットを作成する必要があり、それを呼び出し元が解決します。

あなたには完全に良い点があります、そしてそれは言語への素晴らしい追加になるでしょう。理論的には、それをdeleteの既存のセマンティクスに後付けすることもおそらく可能です。ただし、ほとんどの場合、deleteの全機能を使用するわけではなく、疑似デストラクタ呼び出しの後にarena.release(p)のようなものを使用するだけで十分です。

22
Potatoswatter

すでにptr->~type();があるので、そうする必要はありません。

21
user703016

おそらく、割り当て解除なしでデストラクタを明示的に呼び出すための構文がありましたが(あなたの質問とまったく同じように)、生のメモリで明示的に構築するための構文はありませんでしたか?

8

実際には、コンストラクターが例外をスローした場合に、placementnewを使用して「割り当てられた」オブジェクトの実装によって呼び出される配置削除があります。

ウィキペディアから

プレースメント削除関数は、プレースメントの新しい式から呼び出されます。特に、オブジェクトのコンストラクターが例外をスローした場合に呼び出されます。このような状況では、プログラムでメモリリークが発生しないようにするために、配置削除関数が呼び出されます。

7
Motti

新しい配置の全体的なポイントは、オブジェクトの作成をそのメモリ管理から分離することです。したがって、オブジェクトの破壊中にそれを結び付けることは意味がありません。
オブジェクトのメモリがヒープからのものであり、オブジェクトとそのメモリの有効期間を同じにしたい場合は、operator newoperator deleteを使用します。特別な動作が必要な場合は、それらをオーバーライドします。
[。

2
Tadeusz Kopec