Domanda

Supponiamo che io abbia una struttura "quotata" con una variabile membro puntatore int " i " ;. Allocare memoria sull'heap per i nel costruttore predefinito di s. Più avanti in un'altra parte del codice passo un'istanza di s in base al valore ad una funzione. Sto facendo una copia superficiale qui? Supponiamo che non abbia implementato costruttori di copie o operatori di assegnazione o altro per s ... solo il costruttore predefinito.

È stato utile?

Soluzione

Per dare seguito a ciò che ha detto @ [don.neufeld.myopenid.com], non è solo una copia superficiale, ma è (scegli la tua scelta) una perdita di memoria o un puntatore penzolante.

// 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;
  }
};

Per risolvere il problema, esistono diversi metodi.

Implementa sempre un costruttore di copia e un operatore = nelle classi che utilizzano i puntatori di memoria non elaborata.

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 dire che questo è un grande dolore e ci sono alcune sottigliezze da ottenere. Non sono nemmeno del tutto sicuro di averlo fatto proprio qui e l'ho fatto un paio di volte. Non dimenticare che devi copiare tutti i membri: se ne aggiungi altri nuovi in ??seguito, non dimenticare di aggiungerli anche tu!

Rendi il costruttore della copia e l'operatore = privati ??nella tua classe. Questa è la "serratura della porta". soluzione. È semplice ed efficace, ma a volte iperprotettivo.

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

Non usare mai puntatori non elaborati. Questo è semplice ed efficace. Ci sono molte opzioni qui:

  • Utilizza le classi di stringhe anziché i puntatori a caratteri non elaborati
  • Usa std :: auto_ptr, boost :: shared_ptr, boost :: scoped_ptr ecc

Esempio:

// 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)
  {
  }
};

Altri suggerimenti

Sì, è una copia superficiale. Ora hai due copie di s (una nel chiamante, una nello stack come parametro), ognuna contenente un puntatore allo stesso blocco di memoria.

Avrai due copie della struttura s , ognuna delle quali avrà il suo puntatore i , ma entrambi i puntatori i avranno lo stesso valore che punta allo stesso indirizzo in memoria - quindi sì, sarà una copia superficiale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top