Wie benutzt man ein std :: auto_ptr in einer Klasse, die man konstruieren muss?

8

Ich habe die Klasse foo , die ein std :: auto_ptr-Member enthält, das ich kopieren möchte, aber das scheint nicht erlaubt zu sein. Es gibt eine ähnliche Sache für die Aufgabe. Siehe das folgende Beispiel:

%Vor%

Ich könnte einfach _c als mutable deklarieren, aber ich bin mir nicht sicher, ob das korrekt ist. Hat jemand eine bessere Lösung?

BEARBEITEN

Okay, ich bekomme nicht die Art von Antwort, die ich erwartet habe, also werde ich etwas genauer auf das Problem eingehen.

  • Ein Objekt vom Typ foo wird im Stapel erstellt und nach Wert in eine Containerklasse (nicht in stl) übergeben und verlässt dann den Gültigkeitsbereich. Ich habe keine Kontrolle über den Container-Code. (Es handelt sich tatsächlich um eine aktive Queue-Implementierung mit Fehlern.)
  • Die bar -Klasse ist ein ziemlich schwergewichtiger Parser. Es hat sehr schlechte Leistung auf new und delete , also selbst wenn es kopierbar wäre, wäre es viel zu teuer.
  • Wir können garantieren, dass, wenn ein bar Objekt erstellt wird, es immer nur an einem Ort im selben Besitz sein muss. In diesem Fall wird es zwischen Threads übergeben und gelöscht, wenn die Transaktion abgeschlossen ist. Deshalb habe ich gehofft, ein std::autp_ptr zu verwenden.
  • Ich bin sehr willens, über Smart-Pointer nachzudenken, aber ich habe gehofft, diese Einzigartigkeit zu garantieren, wenn es eine Alternative gibt.
Pascal Dennerly 17.07.2009, 11:11
quelle

9 Antworten

16

Vielleicht möchten Sie folgenden Code versuchen:

%Vor%

(Zuweisungsoperator ist ähnlich.)

Dies funktioniert jedoch nur, wenn bar CopyConstructible ist und wenn das tatsächlich das tut, was Sie wollen. Die Sache ist, dass beide foo Objekte ( _rhs und eine konstruierte) verschiedene Zeiger in _c haben.

Wenn Sie möchten, dass sie den Zeiger teilen, dürfen Sie auto_ptr nicht verwenden, da sie keine gemeinsame Eigentümerschaft unterstützt. Betrachten Sie in diesem Fall die Verwendung von shared_ptr von Boost.SmartPtr (zum Beispiel welches in den neuen C ++ Standard aufgenommen wird). Oder irgendeine andere geteilte Zeigerimplementierung, da dies ein so allgemeines Konzept ist, dass viele Implementierungen verfügbar sind.

    
Adam Badura 17.07.2009, 11:25
quelle
8

Wie Sie herausgefunden haben, können Sie ein std::auto_ptr nicht so kopieren. Nach der Kopie, auf die das Objekt gehört? Stattdessen sollten Sie einen Referenz-Smart-Zeiger verwenden. Die Boost-Bibliothek hat eine shared_ptr , die Sie verwenden könnten.

    
Martin Liversage 17.07.2009 11:21
quelle
3

Zuerst würde ich auto_ptr vermeiden

Die Eigentumsübertragung ist in einigen Szenarien gut, aber ich finde, dass sie selten sind, und "vollwertige" intelligente Zeigerbibliotheken sind jetzt leicht verfügbar. (IIRC auto_ptr war ein Kompromiss, um mindestens ein Beispiel in die Standardbibliothek aufzunehmen, ohne die Verzögerungen, die eine gute Implementierung erfordert hätte.)

Siehe zum Beispiel hier
oder hier

Entscheiden Sie sich für Semantik
Sollte die Kopie von foo einen Verweis auf dieselbe Instanz von bar enthalten? In diesem Fall verwenden Sie boost::shared_ptr oder ( boost::intrusive_ptr ) oder eine ähnliche Bibliothek.

Oder sollte eine tiefe Kopie erstellt werden? (Dies kann manchmal erforderlich sein, beispielsweise wenn ein verzögerter Erzeugungszustand vorliegt). Ich kenne keine Standardimplementierung dieses Konzepts, aber es ist nicht zu komplex, ähnlich aufgebaute Smartpoints zu erstellen.

%Vor%     
peterchen 17.07.2009 11:44
quelle
1

Das std::auto_ptr ist ein gutes Werkzeug, um dynamische Objekte in C ++ zu verwalten, aber um es effektiv zu benutzen, ist es wichtig zu verstehen, wie auto_ptr funktioniert. In diesem Artikel wird erläutert, warum, wann und wo dieser intelligente Zeiger verwendet werden sollte.

In deinem Fall solltest du zuerst entscheiden, was du mit dem Objekt in deinem auto_ptr machen willst. Soll es geklont oder geteilt werden?

Wenn es geklont werden soll, stellen Sie sicher, dass es einen Kopierkonstruktor hat und dann erstellen Sie ein neues auto_ptr, das eine Kopie Ihres Objekts enthält, siehe Adam Badura 's Antwort.

Wenn es geteilt werden soll, sollten Sie boost :: shared_ptr verwenden Martin Liversage vorgeschlagen.

    
Serge 17.07.2009 11:48
quelle
1

Wenn ich eine Klasse habe, die ein auto_ptr enthält und eine Deep-Copy-Semantik haben möchte, mache ich dies im Allgemeinen nur für Klassen mit einem virtuellen Kopieroperator, d. h. klon ().

Dann initialisiere ich innerhalb des Kopierkonstruktors auto_ptr mit einem clone () des anderen; z.B.

%Vor%

clone () wird normalerweise wie folgt implementiert:

%Vor%

Wir erzwingen die Bedingung, dass T klonbar ist, aber diese Bedingung wird im Wesentlichen durch eine kopierbare Klasse mit einem auto_ptr-Member auferlegt.

    
JohnMcG 17.07.2009 17:59
quelle
0

Die ganze Idee von auto_ptr ist, dass es nur einen Besitzer des referenzierten Objekts gibt. Dies bedeutet, dass Sie den Zeiger nicht kopieren können, ohne die ursprüngliche Eigentümerschaft zu entfernen.

Da Sie es nicht kopieren können, können Sie auch kein Objekt kopieren, das ein auto_ptr enthält.

Sie könnten versuchen, move-semantics z. Verwenden von std::swap anstelle von Kopie.

    
xtofl 17.07.2009 11:36
quelle
0

Meine erste Wahl wäre, in dieser Situation auto_ptr zu vermeiden. Aber wenn ich gegen eine Wand gesichert wäre, könnte ich versuchen, das Schlüsselwort mutable in der Deklaration von _c zu verwenden - dies wird es erlauben, sogar von einer const-Referenz zu modifizieren.

    
Mark Ransom 17.07.2009 15:17
quelle
0

Angesichts der Bearbeitung scheint es, dass Sie die Semantik der Eigentumsübertragung übertragen möchten.

In diesem Fall möchten Sie, dass Ihr Kopierkonstruktor und Ihr Zuweisungsoperator nicht-konstante Referenzen auf ihre Argumente akzeptieren und die Initialisierung / Zuweisung dort durchführen.

    
JohnMcG 17.07.2009 18:04
quelle
-1

Sie können const-Referenzen nicht in einem Kopierkonstruktor oder einem Zuweisungsoperator verwenden, der ein auto_ptr<> enthält. Entfernen Sie die Konstante. Mit anderen Worten, verwenden Sie Deklarationen wie

%Vor%

Diese Formulare werden ausdrücklich im Standard erwähnt, hauptsächlich in Abschnitt 12.8. Sie sollten in jeder standardkonformen Implementierung verwendbar sein. In den Absätzen 5 und 10 von 12.8 heißt es nämlich, dass der implizit definierte Kopierkonstruktor bzw. Zuweisungsoperator einen nichtkonstanten Verweis annimmt, wenn eines der Elemente dies erfordert.

    
David Thornley 17.07.2009 15:30
quelle

Tags und Links