Wann möchten Sie verwenden, um eine std :: auto_ptr statt boost :: shared_ptr?
-
22-07-2019 - |
Frage
Wir haben ziemlich viel bewegt über mit boost::shared_ptr
in allen unseren Code, aber noch haben wir einige Einzelfälle, wo wir std::auto_ptr
verwenden, einschließlich Singleton-Klassen:
template < typename TYPE >
class SharedSingleton
{
public:
static TYPE& Instance()
{
if (_ptrInstance.get() == NULL)
_ptrInstance.reset(new TYPE);
return *_ptrInstance;
}
protected:
SharedSingleton() {};
private:
static std::auto_ptr < TYPE > _ptrInstance;
};
Man hat mir gesagt, dass es ein sehr guter Grund, warum dies eine shared_ptr
nicht gemacht wurde, sondern für das Leben von mir, ich kann nicht verstehen, warum? Ich weiß, dass auto_ptr
wird schließlich, wie im nächsten Standard abgeschrieben verkratzt, so möchte ich auf wissen, was / wie ich diese Implementierung ersetzen .
Auch gibt es andere Gründe, warum Sie anstelle eines auto_ptr
ein shared_ptr
betrachten würde mit? Und sehen Sie, irgendwelche Probleme zu bewegen in die Zukunft Shared_ptr?
Edit:
- So in der Antwort auf „kann ich ersetzen sicher
auto_ptr
mitshared_ptr
in dem obigen Code“, lautet die Antwort ja - aber nehme ich eine kleine Performance-Einbußen .
- Wenn
auto_ptr
schließlich als abgeschrieben markiert und wir bewegen uns überstd::shared_ptr
, wir haben unseren Code testen müssen, um sicherzustellen, dass wir durch die unterschiedlichen Eigentums Semantik sind bleibend.
Lösung
auto_ptr
und shared_ptr
lösen ganz andere Probleme. Man ersetzt nicht die anderen.
auto_ptr
ist eine dünne Hülle um Zeiger RAII Semantik zu implementieren, so dass die Ressourcen immer freigegeben , auch wenn Ausnahmen gegenüber. auto_ptr
führt keine Referenzzählung oder dergleichen überhaupt, ist es nicht mehrere Zeiger auf das gleiche Objekt, wenn Kopien zu erstellen. In der Tat ist es ganz anders aus. auto_ptr
ist eine der wenigen Klassen, in denen der Zuweisungsoperator die Quelle modifiziert Objekt. Betrachten Sie diese schamlosen Stecker aus dem auto_ptr Wikipedia-Seite :
int *i = new int;
auto_ptr<int> x(i);
auto_ptr<int> y;
y = x;
cout << x.get() << endl; // Print NULL
cout << y.get() << endl; // Print non-NULL address i
Beachten Sie, wie die Ausführung
y = x;
ändert nicht nur y, sondern auch x.
Die boost::shared_ptr
Vorlage macht es einfach, mehrere Zeiger auf das gleiche Objekt, und das Objekt wird nur dann gelöscht zu handhaben, nachdem der letzte Verweis auf sie außerhalb des Bereichs ging. Diese Funktion ist in Ihrem Szenario nicht sinnvoll, die (versucht) führen ein Singleton . In Ihrem Szenario gibt es immer entweder 0 Verweise auf 1 Bezugnahme auf das einzig Objekt der Klasse, wenn überhaupt.
Im Wesentlichen auto_ptr
Objekte und shared_ptr
Objekte haben ganz andere Semantik (das ist, warum Sie nicht die ehemalige in Containern verwenden können, aber so mit diesem zu tun ist in Ordnung), und ich hoffe, dass Sie gute Tests haben keine Regressionen Sie eingeführt zu fangen während Sie den Code zu portieren. : -}
Andere Tipps
Andere haben geantwortet, warum dieser Code eine auto_ptr
anstelle eines shared_ptr
verwendet. Um richten Sie Ihre Fragen:
Was / wie ich diese Implementierung ersetzen kann?
Verwenden Sie entweder boost::scoped_ptr
oder unique_ptr
(erhältlich in beiden Boost und den neuen C ++ Standard). Sowohl scoped_ptr
und unique_ptr
bieten strenges Eigentum (und keine Kopfreferenzzählung), andthey vermeiden die überraschende Lösch-on-Kopie Semantik von auto_ptr
.
Auch gibt es andere Gründe, warum man bedenkt, würde eine auto_ptr
anstelle eines shared_ptr
verwenden? Und sehen Sie irgendwelche Probleme in der Zukunft shared_ptr
bewegen?
Persönlich würde ich nicht eine auto_ptr
verwenden. Löschen-on-Kopie ist einfach zu nicht-intuitiv. Herb Sutter scheint zustimmen. Die Umstellung auf scoped_ptr
, unique_ptr
oder shared_ptr
sollten keine Probleme bieten. Insbesondere sollte shared_ptr
einen Drop-in seinen Ersatz, wenn Sie nicht über die Referenzzählung Kopf kümmern. scoped_ptr
ist ein Drop-in-Ersatz, wenn Sie nicht auto_ptr
die Transfer-of-Ownership-Funktionen verwenden. Wenn Sie Transfer-of-Ownership verwenden, dann ist unique_ptr
fast ein Drop-in-Ersatz, mit der Ausnahme, dass Sie stattdessen müssen explizit move
nennen Eigentum zu übertragen. Siehe hier für ein Beispiel.
auto_ptr ist die einzige Art von Smart-Pointer ich verwende. Ich benutze es, weil ich nicht-Boost verwenden, und weil ich in der Regel meine Business / anwendungsorientierte Klassen bevorzugen explizit definieren Löschen Semantik und Ordnung, sondern sind abhängig von Sammlungen von oder individuelle, intelligente Zeiger.