web-dev-qa-db-fra.com

Vecteur de pointeurs partagés, problèmes de mémoire après avoir effacé le vecteur

J'ai réalisé qu'après avoir appelé vector.clear() qui contient des pointeurs partagés, les destructeurs de l'objet qui possèdent par shared_ptr Ne sont pas libérés.

Un exemple de code peut être vu ci-dessous. Même vector.clear() étant appelé, le destructeur appelé après le pointeur partagé dépasse la portée. Ma question est - dois-je supprimer manuellement tous les pointeurs intelligents à l'intérieur du vecteur en les réinitialisant? Y a-t-il un moyen plus simple que vous pouvez conseiller?

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
Kadir Erdem Demir

vous avez deux exemplaires de shared_ptr<A> dans ce cas, l'un est la variable sharedptr et l'autre comme élément du vecteur.

faites cela à la place

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

notez maintenant que l'original sharedptr a son déplacement interne et n'est plus utilisable. L'autre chose est de ne rien faire du tout, c'est une utilisation parfaitement valide de shared_ptr et sharedptr se nettoiera une fois qu'il sera hors de portée.

40
yngccc

Le problème se pose lorsque le Push_back ajoute un copie du shared_ptr au vecteur, en laissant le balancement d'origine jusqu'à ce que le principal existe. Si vous ne faites pas le shared_ptr dans la portée principale, le problème ne se produit pas. Évitez simplement de faire le shared_ptr dans la portée principale. Faites-en un droit temporaire dans le Push_back appel.

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

Ici shared_ptr et l'élément dans vector partagent le même objet, ce qui n'invoquera le constructeur et le destructeur qu'une seule fois.

3
daoluan