Question

Dites que j'ai une structure "&"; avec une variable membre de pointeur int "i". J'alloue de la mémoire sur le tas pour i dans le constructeur par défaut de s. Plus tard, dans une autre partie du code, je passe une instance de s par valeur à une fonction. Est-ce que je fais une copie superficielle ici? Supposons que je n’ai mis en oeuvre aucun constructeur de copie, ni opérateur d’assignation, ni rien pour s… juste le constructeur par défaut.

Était-ce utile?

La solution

Pour faire suite à ce que @ [don.neufeld.myopenid.com] a dit, il ne s’agit pas seulement d’une copie superficielle, mais bien d’une fuite de mémoire ou d’un pointeur suspendu.

// memory leak (note that the pointer is never deleted)
class A
{
  B *_b;
  public:
  A()
  : _b(new B)
  {
  }
};

// dangling ptr (who deletes the instance?)
class A
{
  B *_b;
  public:
  A()
  ... (same as above)

  ~A()
  {
    delete _b;
  }
};

Pour résoudre ce problème, il existe plusieurs méthodes.

Implémentez toujours un constructeur de copie et un opérateur = dans les classes qui utilisent des pointeurs de mémoire bruts.

class A
{
  B *_b;
  public:
  A()
  ... (same as above)

  ~A()
  ...

  A(const A &rhs)
  : _b(new B(rhs._b))
  {
  }

  A &operator=(const A &rhs)
  {
    B *b=new B(rhs._b);
    delete _b;
    _b=b;
    return *this;
};

Inutile de dire que ceci est une douleur majeure et qu'il y a pas mal de subtilités à résoudre. Je ne suis même pas tout à fait sûr de l'avoir fait ici et je l'ai fait plusieurs fois. N'oubliez pas que vous devez copier tous les membres. Si vous en ajoutez de nouveaux ultérieurement, n'oubliez pas de les ajouter également!

Définissez le constructeur de la copie et l'opérateur = privé dans votre classe. il s'agit du "verrouiller la porte". Solution. C'est simple et efficace, mais parfois trop protecteur.

class A : public boost::noncopyable
{
  ...
};

N'utilisez jamais de pointeurs bruts. C'est simple et efficace. Il y a beaucoup d'options ici:

  • Utilisez des classes de chaînes au lieu de pointeurs de caractères bruts
  • Utilisez std :: auto_ptr, boost :: shared_ptr, boost :: scoped_ptr etc

Exemple:

// uses shared_ptr - note that you don't need a copy constructor or op= - 
// shared_ptr uses reference counting so the _b instance is shared and only
// deleted when the last reference is gone - admire the simplicity!
// it is almost exactly the same as the "memory leak" version, but there is no leak
class A
{
  boost::shared_ptr<B> _b;
  public:
  A()
  : _b(new B)
  {
  }
};

Autres conseils

Oui, c'est une copie superficielle. Vous avez maintenant deux copies de s (une dans l'appelant, une sur la pile en tant que paramètre), chacune contenant un pointeur sur ce même bloc de mémoire.

Vous aurez deux copies de la structure s , chacune ayant son propre pointeur i , mais les deux pointeurs i auront la même valeur pointant vers la même adresse en mémoire - donc oui, ce sera une copie superficielle.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top