Warum gibst du nicht shared_ptr<>
zurück? Auf diese Weise kann der Client die zurückgegebenen Daten so lange verwenden, wie er benötigt wird. Es gibt jedoch kein Problem, wenn die Klasse "Server" nicht mehr verfügbar ist.
Es gibt nicht viele Situationen, in denen die Semantik von weak_ptr<>
sehr sinnvoll ist (Caches und ???). Wenn ein Kunde nach etwas fragt, möchte er in der Regel Besitz an dem vom Kunden selbst bestimmten Ding haben (und das gemeinsame Eigentum ist genauso gut wie das volle Eigentum).
Wenn Sie eine Situation haben, in der das "Server" -Objekt ohne Kenntnis des Clients zerstört werden kann (eine Situation, in der Sie use weak_ptr<>
oder shared_ptr<>
verwenden möchten), können Sie eine Referenz auf die schlechteste Sache zurückgeben ein Mitglied. In diesem Fall kann der Client nicht wissen, ob der Zugriff auf die zurückgegebene Referenz sicher ist oder nicht. Sie müssen eine Kopie des Members oder einen Smart-Zeiger zurückgeben, der die Lebensdauer des zurückgegebenen Elements korrekt verwalten kann.
Beachten Sie, dass in dem Fall, in dem ein Ausdruck ein temporäres ClassWithCppReference
erzeugt (was nicht immer offensichtlich ist), der Client, der GetMember()
aufruft, nicht in der Lage ist, den zurückgegebenen Verweis in der nächsten Anweisung zu verwenden.
Sie sollten Ihre Interna nicht verschenken; es ist die Leitlinie n. 42 von "C ++ Codierstandards" (Herb Sutter und Andrei Alexandrescu). Wenn Sie aus irgendeinem Grund besser eine const-Referenz und keinen Zeiger zurückgeben müssen, weil sich die -Konstante nicht durch sie ausbreitet.
weak_ptr & lt; & gt; scheint eine praktikable Lösung zu sein, auch wenn ihr Hauptzweck darin besteht, Zyklen von shared_ptr zu vermeiden. Wenn Sie stattdessen shared_ptr & lt; & gt; Sie verlängern das Leben von solchen internen, die in den meisten Fällen keinen Sinn ergeben.
Das Problem mit der Instanz, die verschwindet, während jemand einen Verweis auf seine Interna bearbeitet, sollte mit einer korrekten Synchronisation / Kommunikation zwischen Threads konfrontiert werden.
Ich möchte etwas zu den Kommentaren (vor allem OP und Colomon) über die Effizienz usw. sagen. Oftmals spielt es keine Rolle, ob das Kopieren von Inhalten wirklich wichtig ist, und zwar in Bezug auf die tatsächliche Leistung.
Ich habe Programme geschrieben, die eine Menge defensives Kopieren Es ist ein Idiom in Java, wo, weil alle Objekte mit dem Zeiger übergeben werden, viel Aliasing stattfindet, also kopieren Sie alles, was in Ihre Klasse hinein- und herausgeht, um das Aliasing zu brechen, um sicherzustellen, dass Clients Ihrer Klasse Ihre Klasseninvarianten nicht verletzen können indem Sie ein Objekt nachträglich ändern.
Die Programme, die ich geschrieben habe, haben defensiv ganze Strukturen an Orten kopiert, einschließlich ganzer Listen und Karten. Um sicher zu sein, dass die Leistung nicht beeinträchtigt wird, habe ich das Programm ausführlich beschrieben. Die hauptsächlichen Engpässe waren woanders (und selbst dann habe ich diese anderen Stellen so eingestellt, dass der größte Engpass das Netzwerk ist). Nirgends ist diese defensive Kopie in die Hotspots des Programms eingegangen.
ETA: Ich habe das Bedürfnis, den Sinn meiner Botschaft zu klären, da ein Kommentator es anders liest als ich es beabsichtigt habe, und möglicherweise auch andere es getan haben. Mein Punkt ist nicht, dass es in Ordnung ist, Zeug um Willy-Nilly zu kopieren; aber man sollte immer die Leistung ihres Codes profilieren, anstatt wild zu erraten, wie es funktioniert.
Wenn das Kopieren ganzer Strukturen immer noch akzeptable Leistung bringt und gleichzeitig den Code einfacher zu schreiben macht, dann ist das meiner Meinung nach ein besserer Kompromiss (in den meisten Fällen) als Code, der nur geringfügig schneller ist, aber viel mehr kompliziert.
Ich denke, die einzig vernünftige Antwort ist, dass es darauf ankommt, wie Member mit der Klasse verwandt ist und was die Benutzer der Klasse tun sollen. Hat _member
eine sinnvolle Existenz, die unabhängig vom Klassenobjekt ist? Wenn nicht, dann glaube ich nicht, dass die Verwendung von shared_ptr
sinnvoll ist, egal ob Sie eine weak_ptr
oder eine shared_ptr
zurückgeben. Im Wesentlichen würde entweder der Benutzer Zugriff auf ein Member-Objekt erhalten, das das Klassenobjekt überleben könnte, das ihm Bedeutung gibt. Das könnte einen Absturz verhindern, aber auf Kosten eines schwerwiegenden Entwurfsfehlers.
Wie awgn angibt, sollten Sie sehr vorsichtig sein, wenn Sie Ihre Klasseninterna offen legen. Aber ich denke, da ist definitiv ein Platz dafür. Zum Beispiel habe ich eine Klasse in meinem Code, die ein Dateiobjekt darstellt, das aus einem Dateikopfobjekt und einem Dateidatenobjekt besteht. Eine vollständige Duplizierung der Header-Schnittstelle in der Dateiklasse wäre albern und würde DRY verletzen. Sie könnten, denke ich, den Benutzer zwingen, eine Kopie des Header-Objekts zu erhalten, die Änderungen an der Kopie vorzunehmen und dann das externe Objekt wieder in die gesamte Dateiklasse zu kopieren. Aber das führt zu einer Menge Ineffizienz, die Ihnen nur die Möglichkeit einräumt, die Dateiobjektdarstellung des Headers anders als die Headerobjektdarstellung zu machen. Wenn Sie sicher sind, dass Sie das nicht möchten, können Sie auch einen nichtkonstanten Verweis auf den Header zurückgeben - das ist einfacher und effizienter.
Warum einen schwachen Zeiger zurückgeben? Ich denke, Sie machen es komplizierter, ohne dass es notwendig ist.
Meine grundlegende, unwissende Richtlinie:
Ich nehme an, dass letzteres unsicher sein kann, wenn die Instanz von ClassWithCppReference weggehen kann, während jemand noch einen Verweis auf ein Mitglied hat. Allerdings kann ich auch ein Argument für die letztere Klasse mit POD-Typen sehen, wie zum Beispiel eine Nachricht an ein Gerät, und Sie wollten das Mitglied nicht die ganze Zeit kopieren.
In den meisten Situationen würde ich
bereitstellen %Vor% Der Grund dafür ist, dass (auch ich und wahrscheinlich viele andere) die Methode GetMember()
aufrufen, dass Class
besitzt member
und daher die zurückgegebene Referenz
wird nur für die Lebensdauer des enthaltenen Objekts gültig sein.
In den meisten (aber nicht allen) Codes, die mir begegnet sind, werden GetMember()
-Methoden im Allgemeinen verwendet, um Dinge mit dem zurückgegebenen Mitglied sofort zu erledigen und nicht für spätere Benutzer zu speichern. Wenn Sie Zugriff auf das Mitglied benötigen, können Sie es jederzeit jederzeit aus dem enthaltenen Objekt anfordern.
Je nach Kontext könnte beides in Ordnung sein. Das Hauptproblem beim Zurückgeben einer "Live" -Verbindung zu einem Mitglied (wenn Sie eine Person zuerst aufdecken müssen) ist, dass derjenige, der das exposed-Mitglied verwendet, länger daran festhält, als das enthaltene Objekt existiert. Und wenn Ihr Client über eine Referenz auf dieses Mitglied zugreift, wenn sein enthaltendes Objekt den Gültigkeitsbereich verlässt, werden Sie mit "merkwürdigen" Abstürzen, falschen Werten und ähnlichem Spaß konfrontiert. Nicht empfohlen.
Zurückgeben des weak_ptr & lt; & gt; hat den großen Vorteil, dass es dem Client mitteilen kann, dass das Objekt, auf das sie zugreifen, nicht mehr existiert, was die Referenz nicht kann.
Mein Wert von 2 Pfennigen wäre: