web-dev-qa-db-ja.com

共有ポインタのベクトル、ベクトルをクリアした後のメモリの問題

共有ポインターを保持するvector.clear()を呼び出した後、_shared_ptr_が所有するオブジェクトのデストラクターが解放されないことに気付きました。

コード例を以下に示します。 vector.clear()が呼び出されても、共有ポインタがスコープを超えた後にデストラクタが呼び出されます。私の質問は、ベクトル内のすべてのスマートポインタをリセットして手動で削除する必要がありますか?アドバイスできる簡単な方法はありますか?

_Output :   

constructor
I am here
destructor

Code:

#include <vector>
#include <iostream>
#include <memory>

using namespace std;

class A
{
public:
    A(){cout << "constructor" << endl;};
    ~A(){cout << "destructor"  << endl;};
};

int main( )
{
    shared_ptr<A> sharedptr (new A);
    std::vector<shared_ptr<A> > test;
    test.Push_back(sharedptr);

    test.clear();
    cout << "I am here" << endl;
}
_
21

この場合、shared_ptr<A>の2つのコピーがあります。1つはsharedptr変数で、もう1つはベクトルの要素としてです。

代わりにこれを行う

test.Push_back(std::move(sharedptr));

元のsharedptrは内部的に移動され、使用できなくなっていることに注意してください。もう1つは、何もしないでください。これはshared_ptrの完全に有効な使用方法であり、sharedptrはスコープ外になった後にそれ自体をクリーンアップします。

40
yngccc

この問題は、Push_backshared_ptrの-​​copyをベクターに追加し、mainが存在するまで元のダングリングを残したときに発生します。 shared_ptrをメインスコープで作成しない場合、問題は発生しません。 shared_ptrをメインスコープにしないでください。 Push_back呼び出しの一時的な権利として作成してください。

Output is now:   

constructor
I am almost there
destructor
I am here

New code:

#include <vector>
#include <iostream>
#include <memory>

using namespace std;

class A
{
public:
  A(){cout << "constructor" << endl;};
  ~A(){cout << "destructor"  << endl;};
};

int main( )
{
  vector<shared_ptr<A> > test;
  test.Push_back(shared_ptr<A>(new A));
  cout << "I am almost there" << endl;
  test.clear();
  cout << "I am here" << endl;
  return 0;
}
5
Fred Jackson

ここでshared_ptrvectorの要素は同じオブジェクトを共有するため、コンストラクターとデストラクターは1回だけ呼び出されます。

3
daoluan