2012-05-31 7 views
6

Stellen Sie sich ein class C, die eine Membervariable m_MyList Typ hat std::vector, in dem ich MyClass Objekte vom Typ gespeichert werden sollen. C verfügt über zwei Funktionen zum Hinzufügen oder Entfernen von Objekten in m_MyList. m_MyList sollte auch für die Verbraucher von C zugänglich gemacht werden, da sie die Sammlung von MyClass Objekte lesen müssen. Der externe Leser der Sammlung hat keine Möglichkeit, die Sammlung zu ändern, daher sind die MyClass Objekte nur im Besitz von C.Sollte ich std :: unique_ptr <T> in einer std :: vector Membervariable in meiner Klasse verwenden?

Jetzt meine Frage: In C++ 11 Stil, was ist die beste T in den Vektor zu speichern? Die Möglichkeiten scheinen zu sein:

  • std::vector<MyClass>
  • std::vector<MyClass*>
  • std::vector<unique_ptr<MyClass>>, std:move mit dem unique_ptr in die vector
+3

Die 'unique_ptr'-Lösung kauft Ihnen wirklich nichts, es sei denn, die Objekte sind nicht kopierbar. Die rohe Zeigerversion ist ausgesprochen schädlich. Wählen Sie einfach die einfache Lösung – jalf

+0

Wie groß ist ein Objekt "MyClass" und wie viele möchten Sie speichern? Wird es viele einzelne Insertionen geben? – RedX

Antwort

13

drücken Wenn die MyClass Objekte von C gehören, dann ist die beste Option wäre die einfachste:

std::vector<MyClass> 

Der einzige Grund, den ich für die Verwendung von std::unique_ptrs hier sehen könnte, ist, wenn Sie Zeiger auf eine Basisklasse für Polymorphismus halten müssen. In diesem Fall dienen die unique_ptrs dem Zweck, Ressourcen bei der Zerstörung des Vektors freizugeben. Aber dann sollte die C Schnittstelle Eigentum an den Clients nicht übertragen.

+5

'MyClass' könnte ein Objekt sein, das teuer zu verschieben/kopieren ist. Mit einem Zeiger können Sie die Größe des Vektors ändern, ohne viel Speicher kopieren zu müssen. –

+1

@ edA-qamort-ora-y das ist wahr, aber es ist unabhängig von Eigentum und Kunden und so weiter, so nahm ich an, dass die Überlegung über den Rahmen der Frage zu sein. – juanchopanza

+1

Der andere Grund, einen Referenztyp als Mitglied einer Klasse zu verwenden, besteht darin, sicherzustellen, dass der Header keine Details dieser Member offenlegt, während die Unit-Datei (cpp) davon weiß. Es ist eigentlich gut für die Isolation. Hier erfordert der Vektor, dass MyClass definiert wird, bevor das Element definiert wird. Sie müssen also den MyClass-Code einfügen. In manchen Fällen wollen Sie das nicht. Abgesehen davon, dass die Speicher- und Verwaltungskosten unterschiedlich sind, ist die Auswahl sehr kontextspezifisch. – Klaim

11

Rohe Zeiger (std::vector<MyClass*>) sind falsch, wenn C die Objekte besitzt. Die anderen beiden sind ziemlich ähnlich mit den folgenden Abwägungen:

  • std::vector<MyClass> - MyClass kopierbar sein erfordert und/oder bewegen-able
  • std::vector<unique_ptr<MyClass>> - erfordert (zusätzliche) dynamische Zuweisungen

Die Art von Operationen, die an dem Container ausgeführt werden, können ebenfalls relevant sein. Um ein extremes Beispiel zu nehmen: Wenn MyClass groß ist und der Container wiederholt gemischt wird, wäre unique_ptr die bessere Wahl.

+0

Jedes Element eines 'std :: vector' wird auf den freien Speicher gelegt, also sagt" benötigt dynamische Zuweisungen "wie es eine schlechte Sache ist, ist hier eine Art Fehlbezeichnung ... – rubenvb

+2

@rubenvb: der Vektor benötigt nur eine dynamische Zuweisung zu einer Zeit (oder kurz 2 während der Umverteilung). Daher ist keine dynamische Zuweisung erforderlich ;-) Wenn 'MyClass' klein genug ist, werden Sie den Unterschied bemerken. Ich nehme an, es wäre besser zu sagen, "benötigt mehr Overhead in dynamischen Zuweisungen". Es ist eine schlechte Sache, wenn Sie zusätzlichen Code eingeben, um Speicher zu verschwenden. Es kann * eine schlechte Sache sein, wenn 'MyClass' nicht zu konstruieren ist, und Sie dynamische Zuordnungen an Stellen einführen, an denen sie sonst nicht vorkommen würden, wodurch Ausnahmen eingeführt werden. –

+0

Die dynamische Zuweisung jedes einzelnen Objekts benötigt nicht nur mehr Speicher, sondern erhöht auch die Fragmentierung und verursacht mehr Datencache-Fehler. In den meisten Codes wird es völlig unbemerkbar sein, aber wie Steve sagt - tippe nicht mehr, um den Code etwas schlechter zu machen. –