2016-09-02 10 views
0

私はすでにスタック上に作成されたオブジェクトの新しい配置するだろう場合:配置新しいオーバーライドし、既存のオブジェクト

struct s{ 
s() { std::cout << "C\n";} 
~s() { std::cout << "D\n";} 
}; 

int main() { 
     s s1[3]; 
     for(int i=0; i< 3; ++i) 
       s* newS = new (&s1[i]) s(); 
} 

を私が手:

C 
C 
C 
C 
C 
C 
D 
D 
D 

は、だから我々は最初の3つのオブジェクトのデストラクタを取得されていませんそれは安全ですか?ヒープ/スタックに割り当てられたオブジェクトのメモリをオーバーライドするだけで、そのオブジェクトがデストラクタでリソースを解放する必要がない場合でも安全ですか?

+0

私はあなたがスタック上に3つのオブジェクトを作成している、これは間違っているどのように表示されていない、あなたはそれらの3のコンストラクタを取得する - そしてあなたは再作成するための新しい配置を使用します3つのオブジェクトを再び同じ場所に置くと、3つのコンストラクタが再び得られ、最後に3つのデストラクタが得られます。あなたは何か違うことを期待していますか? –

+1

一般的に言えば、それは安全ではありません。基本ストレージを再利用する前に、構築されたオブジェクトを明示的に破棄する必要があります。 –

+0

非常に安全ではありません - デストラクタが呼び出されるのは、新しい3つの配置で作成された3つのオブジェクトではなく、元の3つのオブジェクトです。これは驚きを引き起こす可能性があります。 –

答えて

2

wandbox example

あなたの出力は予想外ではありません - placement newはあなたがアクセスしているメモリ位置に格納されている任意の潜在的なオブジェクトのデストラクタを呼び出すことはありません。 プレースメントnewを安全に使用するために、使用しようとしているメモリの場所を占有するオブジェクトのうち、explictly invoke the destructorが必要です。

struct s 
{ 
    s() 
    { 
     std::cout << "C\n"; 
    } 
    ~s() 
    { 
     std::cout << "D\n"; 
    } 
}; 

int main() 
{ 
    // Three 's' instances are constructed here. 
    s s1[3]; 

    // (!) You need to explicitly destroy the existing 
    // instances here. 
    for(int i = 0; i < 3; ++i) 
    { 
     s1[i].~s(); 
    } 

    for(int i = 0; i < 3; ++i) 
    { 
     // Three 's' instances are constructed here. 
     s* newS = new(&s1[i]) s(); 
    } 

    // Three 's' instances are destroyed here. 
} 

出力:

C 
C 
C 
D 
D 
D 
C 
C 
C 
D 
D 
D 
+0

明示的にデストラクタを呼び出すことは良いことですか?これを考慮{ クラスfoo; foo。〜クラス(); }はデストラクタを2回呼び出します –

+0

@SamerTufail:これは「良いか悪い」ではありません。新しい配置で作業する場合は**必須**です。あなたの例は新しい配置を使用しないので、デストラクタを明示的に呼び出す必要はありません。 –

+0

私は知っています。あなたは、スタックに明示的に割り当てられたオブジェクトを破壊し、新しい配置を使用してオブジェクトを再作成していることを指摘してください。ヒープにあらかじめ決められたサイズを割り振り、それを使って、このような方法でメモリプールを使用するのではなく、メモリプールの仕組みであるオブジェクトを作成する方がよいでしょう。 –

関連する問題