Soll ich shared_ptr oder unique_ptr verwenden

Lesezeit: 6 Minuten

Soll ich shared ptr oder unique ptr verwenden
Clinton

Ich habe einige Objekte mit dem Pimpl-Idiom erstellt, bin mir aber nicht sicher, ob ich es verwenden soll std::shared_ptr oder std::unique_ptr.

ich verstehe das std::unique_ptr ist effizienter, aber das ist für mich nicht so sehr ein Problem, da diese Objekte sowieso relativ schwer sind, also die Kosten std::shared_ptr über std::unique_ptr ist relativ gering.

Ich gehe derzeit mit std::shared_ptr gerade wegen der zusätzlichen Flexibilität. Zum Beispiel mit a std::shared_ptr ermöglicht es mir, diese Objekte für den schnellen Zugriff in einer Hashmap zu speichern und gleichzeitig Kopien dieser Objekte an Aufrufer zurückzugeben (da ich glaube, dass alle Iteratoren oder Referenzen schnell ungültig werden können).

Allerdings werden diese Objekte in gewisser Weise nicht wirklich kopiert, da Änderungen alle Kopien betreffen, also habe ich mich gefragt, ob dies vielleicht der Fall ist std::shared_ptr und das Zulassen von Kopien ist eine Art Anti-Pattern oder eine schlechte Sache.

Ist das richtig?

  • Die Verwendung des einen oder anderen verändert die Semantik des Kopierens, die Sie Ihren Objekten geben, grundlegend. Es gibt Verwendungen für beide. Ich würde sagen, das ist idiomatischer in der C++-Welt unique_ptr, aber Objekte mit gemeinsam genutzten Implementierungen haben ihre Verwendung, insbesondere wenn Sie “fremden” Code schreiben (z. B. COM, C++/CLI) oder wenn die Klasse wirklich wie ein “Referenztyp” aussieht.

    – Alexander C.

    7. April 11 um 8:38 Uhr

  • Ähnliche Frage: stackoverflow.com/questions/311166/…

    – Rolf Kristensen

    21. November 11 um 22:31 Uhr

  • Der empfohlene Weg in C++11 ist die Verwendung von unique_ptr, schließlich müssen Sie die Implementierung nicht kopieren oder mit anderen teilen. Auch unique_ptr ist zur Laufzeit schneller.

    – Damian

    8. Juni 16 um 16:30 Uhr

Ich habe einige Objekte mit dem Pimpl-Idiom erstellt, bin mir aber nicht sicher, ob ich es verwenden soll shared_ptr oder unique_ptr.

Bestimmt unique_ptr oder scoped_ptr.

Pimpl ist kein Muster, sondern ein Idiom, das sich mit Kompilierzeitabhängigkeit und Binärkompatibilität befasst. Sie sollte die Semantik der Objekte, insbesondere hinsichtlich ihres Kopierverhaltens, nicht beeinflussen.

Sie können unter der Haube jede Art von intelligentem Zeiger verwenden, aber diese 2 garantieren, dass Sie die Implementierung nicht versehentlich zwischen zwei unterschiedlichen Objekten teilen, da sie eine bewusste Entscheidung über die Implementierung des Kopierkonstruktors und des Zuweisungsoperators erfordern.

Allerdings werden diese Objekte in gewisser Weise nicht wirklich kopiert, da Änderungen alle Kopien betreffen, also habe ich mich gefragt, ob dies vielleicht der Fall ist shared_ptr und das Zulassen von Kopien ist eine Art Anti-Pattern oder eine schlechte Sache.

Es ist kein Antimuster, sondern ein Muster: Aliasing. Sie verwenden es bereits in C++ mit bloßen Zeigern und Referenzen. shared_ptr bieten ein zusätzliches Maß an “Sicherheit”, um tote Referenzen zu vermeiden, auf Kosten zusätzlicher Komplexität und neuer Probleme (achten Sie auf Zyklen, die Speicherlecks verursachen).


Unabhängig von Pimpl

ich verstehe unique_ptr ist effizienter, aber das ist für mich nicht so sehr ein Problem, da diese Objekte sowieso relativ schwer sind, also die Kosten shared_ptr über unique_ptr ist relativ gering.

Wenn Sie einen Zustand ausklammern können, sollten Sie sich die ansehen Fliegengewicht Muster.

  • Wollen Sie damit sagen, dass Kopierkonstruktoren normalerweise tiefe Kopien (oder etwas funktional Äquivalentes, dh Kopieren beim Schreiben) mit Ausnahme von Zeigern/intelligenten Zeigern ausführen sollten?

    – Clinton

    7. April 11 um 7:48 Uhr


  • @Clinton: Semantisch ist eine Kopie von ihrer Quelle getrennt, die Implementierungsdetails interessieren den Benutzer nicht 🙂 In C++ ist dies für Zeiger und Referenzen nicht der Fall, aber das Vokabular wurde nie wirklich angepasst, daher die Umständlichkeit wann diese Aspekte zu diskutieren. .. Ob Sie in Ihrem Fall eine tiefe Kopie oder eine flache Kopie bevorzugen, sollte nur von der Semantik abhängen, die Sie Ihrer Klasse geben möchten, und die Implementierung wird folgen.

    – Matthias M.

    7. April 11 um 8:27 Uhr

  • aber das Vokabular wurde nie wirklich angepasst” Was meinst du?

    – Neugieriger

    8. Oktober 11 um 16:54 Uhr

  • @curiousguy: 5 Monate nach 😡 ? Ich denke, mein Punkt war, dass ein “Kopier” -Konstruktor, der eine flache Kopie erstellt, irgendwie seltsam war, aber wirklich … ich bin mir nicht sicher: p

    – Matthias M.

    8. Oktober 11 um 17:29 Uhr

  • @Frank: COW ist eine Option (und das habe ich gesagt shared_ptr wurde an einige Fälle angepasst), aber wir sprachen hier von Pimpl; es ist nicht einer dieser Fälle, wo shared_ptr angepasst ist.

    – Matthias M.

    1. Juni 12 um 6:14 Uhr

Wenn du benutzt shared_ptr, es ist nicht wirklich die klassische Pickel-Redewendung (es sei denn, Sie unternehmen zusätzliche Schritte). Aber die eigentliche Frage ist, warum Sie überhaupt einen intelligenten Zeiger verwenden möchten. es ist sehr klar, wo die delete auftreten sollte, und es gibt kein Problem mit Ausnahmesicherheit oder anderem, mit dem man sich befassen müsste. Mit einem intelligenten Zeiger sparen Sie höchstens ein oder zwei Zeilen Code. Und die einzige, die die richtige Semantik hat, ist boost::scoped_ptr, und ich glaube nicht, dass es in diesem Fall funktioniert. (IIRC, es erfordert einen vollständigen Typ, um instanziiert zu werden, aber ich könnte mich irren.)

Ein wichtiger Aspekt des Pickel-Idioms ist, dass seine Verwendung für den Kunden transparent sein sollte; die Klasse soll sich genauso verhalten, als wäre sie klassisch implementiert. Dies bedeutet entweder das Verhindern von Kopieren und Zuweisen oder das Implementieren von Deep Copy, es sei denn, die Klasse ist unveränderlich (keine nicht konstanten Elementfunktionen). Keiner der üblichen Smart Pointer implementiert Deep Copy; Sie könnten natürlich einen implementieren, aber es würde wahrscheinlich immer noch einen vollständigen Typ erfordern, wenn die Kopie auftritt, was bedeutet, dass Sie immer noch einen benutzerdefinierten Kopierkonstruktor und einen Zuweisungsoperator bereitstellen müssten (da sie nicht inline sein können). Angesichts dessen lohnt es sich wahrscheinlich nicht, den Smart Pointer zu verwenden.

Eine Ausnahme besteht, wenn die Objekte unveränderlich sind. In diesem Fall spielt es keine Rolle, ob die Kopie tief ist oder nicht, und shared_ptr
meistert die Situation vollständig.

Soll ich shared ptr oder unique ptr verwenden
Nim

Wenn Sie a verwenden shared_ptr (z.B. in einem Container, dann nachschlagen und zurückgeben nach Wert), verursachen Sie keine Kopie des Objekts, auf das es zeigt, sondern lediglich eine Kopie des Zeigers mit einem Verweiszähler.

Das bedeutet, wenn Sie das zugrunde liegende Objekt von mehreren Punkten aus ändern, wirken Sie sich auf die Änderungen aus gleiche Instanz. Genau dafür ist es konzipiert, also nicht für einige Anti-Muster!

Beim Passieren von a shared_ptr (wie die Kommentare sagen) ist es besser, die const-Referenz zu übergeben und bei Bedarf zu kopieren (dort durch Erhöhen der Referenzanzahl). Was die Rücksendung betrifft, von Fall zu Fall.

  • Das ist ein guter Ratschlag, aber ich denke, “immer nach Wert übergeben und zurückgeben” ist ein bisschen stark. Die Präferenz besteht darin, eine const-Referenz oder eine rvalue-Referenz zu übergeben. Das Übergeben einer einfachen, modifizierbaren Referenz ist manchmal sogar noch angemessen.

    – Kartoffelklatsche

    7. April 11 um 6:47 Uhr

  • @Johann: Ah, ich habe über die Auswirkung von Pass-by-Value auf ein Objekt mit einem Mitglied (Pimpl) nachgedacht. shared_ptr oder unique_ptr. In diesem Zusammenhang sollte der Smart Pointer selbst nicht herumgereicht werden.

    – Kartoffelklatsche

    7. April 11 um 7:27 Uhr

  • @Johann Gerell: Nein, bist du nicht soll shared_ptr als Wert übergeben. Sie können, aber das ist nicht der empfohlene Weg. Die empfohlene Methode besteht darin, sie als const-Referenz zu übergeben. Dies ist sowohl effizienter als das Kopieren eines shared_ptr als auch absolut sicher, da gleichzeitige Lesevorgänge derselben shared_ptr-Instanz gemäß der shared_ptr-Dokumentation in Ordnung sind.

    – Antred

    26. August 14 um 13:04 Uhr

1642794665 81 Soll ich shared ptr oder unique ptr verwenden
Posaune

Ja, bitte verwenden Sie sie. Einfach ausgedrückt, der shared_ptr ist eine Implementierung von Smart Pointer. unique_ptr ist eine Implementierung des automatischen Zeigers:

.

580110cookie-checkSoll ich shared_ptr oder unique_ptr verwenden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy