Frage

Sagen, ich habe eine Struktur „s“ mit einem int-Zeiger-Membervariable „i“. Ich weise Speicher auf dem Heap für i im Standard-Konstruktor s. Später in einem anderen Teil des Codes gebe ich eine Instanz von s von Wert bis zu einem gewissen Funktion. Mache ich eine flache Kopie hier? Angenommen, ich habe implementieren keine Kopierkonstruktoren oder Zuweisungsoperatoren oder alles für s ... nur der Standardkonstruktor.

War es hilfreich?

Lösung

Um sich zu verfolgen, was @ [don.neufeld.myopenid.com] sagte, ist es nicht nur eine flache Kopie, aber es ist entweder (nehmen Sie Ihre Wahl) ein Speicherleck oder einen baumelnden Zeiger.

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

Um dies zu lösen, gibt es mehrere Methoden.

implementieren immer eine Kopie Konstruktor und Operator = in Klassen, die rohen Speicherzeiger verwenden.

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

Unnötig zu sagen, dies ist ein großer Schmerz und es gibt durchaus ein paar Feinheiten richtig zu machen. Ich bin nicht einmal ganz sicher, ich habe es hier und ich habe es ein paar Mal getan. Vergessen Sie nicht, müssen Sie alle Mitglieder kopieren - wenn Sie einige neue hinzufügen später, vergessen Sie nicht, sie in auch addieren

Machen Sie den Copy-Konstruktor und Operator = in Ihrer Klasse privat. Dies ist die "die Tür" Lösung. Es ist einfach und effektiv, aber manchmal überSchutz.

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

Nie rohe Zeiger verwenden. Das ist einfach und effektiv. Es gibt viele Möglichkeiten:

  • Verwenden Sie String-Klassen statt roher char Zeiger
  • Verwenden Sie std :: auto_ptr boost :: shared_ptr boost :: scoped_ptr usw.

Beispiel:

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

Andere Tipps

Ja, das ist eine flache Kopie. Sie haben nun zwei Kopien von s (ein in den Anrufern, einen auf dem Stapel als Parameter), die jeweils den einen Zeiger auf den gleichen Speicherblock enthalten.

In Kürze erhalten Sie haben zwei Kopien der s Struktur, von denen jede ihre eigenen i Zeiger haben, aber beide i Zeiger den gleichen Wert auf die gleiche Adresse im Speicher zeigen haben - also ja, es wird eine flache Kopie sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top