20
char * buf = new char[sizeof(T)];
new (buf) T;
T * t = (T *)buf;
//code...
//here I should destruct *t but as it is argument of template and can be
//instantiated via basic types as well (say int) so such code 
/*t->~T();*/
//is incorrect (maybe correct? Strange, but it works on VS 2005 for basic types.)
//and this code 
/*delete t;*/ 
//crashes the program.
delete [] buf;

では、破壊する正しい方法は何tですか?

PS 上記のコードは、私の問題を説明するためだけのものであり、これから書くコードとは実際には関係ありません。したがって、次のような回答はしないでください (new非配置ではなく配置を使用するのはなぜですか? など)。

4

4 に答える 4

27

...基本的なタイプでもインスタンス化されるため(たとえばint)、そのようなコード
t->~T();は正しくありませ
ん...

違う。Tそのコードは、プリミティブ型である可能性がある場合でも、テンプレート コードでは正当で正しいものです。

C++ 標準: 5.4.2

5.2.4疑似デストラクタ呼び出し [expr.pseudo]

  1. .ドットまたは矢印演算子の後の疑似デストラクタ名の使用は、->type-name で指定された非クラス型のデストラクタを表します。結果は関数呼び出しのオペランドとしてのみ使用され、operator ()そのような呼び出しの結果は型 void を持ちます。唯一の効果は、ドットまたは矢印の前の後置式の評価です。
  2. ドット演算子の左辺はスカラー型でなければなりません。アロー演算子の左側は、スカラー型へのポインターでなければなりません。このスカラー型はオブジェクト型です。疑似デストラクタ名で指定する型は、オブジェクトの型と同じでなければなりません。さらに、フォームの pseudodestructor-name 内の 2 つの type-name は::opt nested-name-specifieropt type-name :: ˜ type-name、同じスカラー型を指定する必要があります。オブジェクト型と疑似デストラクタ名で指定された型の cv 修飾されていないバージョンは、同じ型でなければなりません。
于 2011-07-18T08:41:06.123 に答える
12

最初に、デストラクタを直接呼び出してオブジェクトを破棄します。

t->~T();

次に、 :delete[]から返されたポインタを呼び出してメモリを破棄します。new[]

delete []buf;
于 2011-07-18T08:41:25.530 に答える
7

デストラクタを呼び出す

T * t = (T *)buf;
t->~T();

次に、でメモリを解放しますdelete[] buf。デストラクタを明示的に呼び出すことは、placementで作成されたオブジェクトに対して行われる方法とまったく同じですnew

于 2011-07-18T08:41:08.810 に答える
3

メモリは実際にはchar*;を使用して割り当てられました。を使用して適切に解放しています delete[] buft->~T()この場合、デストラクタを呼び出す必要がありますt。する必要はありませんdelete t;

この場合の配置 newは、メモリ割り当て用ではなく、オブジェクトを構築するためにのみ使用されます。

于 2011-07-18T08:43:40.787 に答える