2009-03-10 11 views
9

Ich habe ein Projekt, das ich mehr Smart-Pointer verwenden möchte. Insgesamt war ich bei diesem Ziel erfolgreich. Ich bin jedoch auf einige Dinge gestoßen, bei denen ich nicht sicher bin, was die "beste Praxis" ist.Zurückgeben eines "Pointers", der von einem Smart Pointer gehalten werden muss

Grundsätzlich möchte ich einen "Zeiger" von einer Funktion zurückgeben, aber erfordern, dass der Benutzer es in einem Smart-Zeiger halten. Nicht nur das, ich möchte keinen bestimmten Smart Pointer (Shared vs. Scoped) vorschreiben.

Das Problem ist meistens, dass es scheint nicht zu einem richtigen Weg, um ein scoped_ptr zu einem shared_ptr zu aktualisieren (das wäre die ideale Lösung, die ich denke). Ich verstehe, warum sie dies nicht getan haben, da es die Übertragung von Eigentumsrechten erlauben würde, die zu einigen Problemen führen können, wie diese std::auto_ptr hat.

Übertragung scheint jedoch eine gute Idee für dieser Fall. So ist meine Idee so:

// contrived example of factory pattern 
std::auto_ptr<A> func() { return std::auto_ptr<A>(new A); } 

Dies funktioniert „ok“, da beide scoped_ptr und shared_ptr Konstrukteure haben, die von einem std::auto_ptr Besitz nehmen.

Also meine Frage ist, ist das gute Praxis? Gibt es eine bessere Lösung? Die einzige wirkliche Alternative, die ich habe in der Lage gewesen, mit zu kommen ist eine Vorlage Vorlage als Rückgabewert wie folgt aus:

// similar to above example 
template <template <typename> class P> 
P<A> func() { return P<A>(new A); } 

die könnte tatsächlich gut funktionieren, außer, dass ich denke, es ist etwas Arbeit benötigen würde, um es zu arbeite mit einem scoped_ptr auch.

Gedanken?

Antwort

11

std::auto_ptr Verwendung ist die gute Praxis in der Tat such example wurde von Bjarne Stroustrup vorgeschlagen.

Die Umzugs-Semantik von auto_ptr gibt Ihnen die richtigen Werkzeuge, um damit umzugehen.

Zum Beispiel:

auto_ptr<Foo> make_foo() 
{ 
    return auto_ptr<Foo>(new Foo); 
} 

Foo *raw_pointer=make_foo().release(); 
shared_ptr<Foo> shared_pointer=make_foo(); 
auto_ptr<Foo> auto_pointer=make_foo(); 

Wenn Sie shared_ptr kehren Sie in den normalen Zeiger nicht Rückfall kann mit auto_ptr Sie können. Sie können immer auto_ptr auf gemeinsame aber nicht andere Richtung aktualisieren.

Ein weiterer wichtiger Punkt, shared_ptr verwendet atomare Referenzzählung, das ist viel langsamer , dass einfache und dennoch voll effiziente Arbeit, die auto_ptr tut.

S.S .: scoped_ptr ist nur Version von auto_ptr für pools --- es ist nicht kopierbar und hat nicht standardmäßig constructor. Es ist mehr wie "weniger verwirrend" Version von auto_ptr, im Vergleich zu shared_ptr ist es nicht in tr1. Im Allgemeinen gibt es keine viele Vorteile von scoped_ptr über auto_ptr mit

+0

shared_ptr in der einzelnen Thread-Erstellung verwendet keine atomare Referenzzählung. –

+0

Sie haben Recht, aber standardmäßig Boost ist in Multi-Thread-Version gebaut. – Artyom

+2

Der Vorteil der Verwendung von scoped_ptr gegenüber auto_ptr ist, wenn Sie deutlich machen wollen, dass Sie den Zeiger nicht kopieren sollen. Das geht mit scoped_ptr einfach nicht. Es geht darum, Ihre Absichten zu vermitteln, genau wie in Ihrem Beispiel mit auto_ptr und Eigentumsübertragung. –

3

Wenn Sie eine Fabrik bauen, ist das in Ordnung, dass Sie einfach einen Zeiger zurückgeben. Und der Benutzer Ihrer Fabrik kann selbst entscheiden, wie und wohin er diesen Zeiger setzen soll.
Wenn Sie die Verwendung von Smartpointer erzwingen müssen, müssen Sie die Auswahl einschränken, da Sie nicht möchten, dass sie "falsche" verwenden.
So boost :: shared_ptr. Aber besser, um es dann zu MyClassPtr oder MyClass :: ptr zu schreiben.
Noch Fabriken sind sie wie "neu". Wenn ich will, gebe ich das Ergebnis von new in std :: auto_ptr ein. Aber ich möchte nicht gezwungen sein, die "Freigabe" all die Zeiten zu nennen, wenn ich keinen intelligenten Zeiger will.

+0

true, aber ich möchte die Verwendung eines Smart-Pointer erzwingen, wenn möglich. –

+0

Ich stimme zu, wir sind alle Erwachsene hier. Geben Sie einen leeren Zeiger zurück und lassen Sie den Benutzer des Codes entscheiden, wie der Rückgabewert am besten erfasst werden soll. Ich glaube, dass shared_ptrs Konstruktor von einem auto_ptr weggeht (auto_ptr wird veraltet sein). –

+0

Wenn auto_ptr in C++ 0x bereinigt ist, wird unique_ptr es ersetzen. Ich würde dann zu unique_ptr zurückkehren. – Aaron

1

Mit C++ 11 Sie sollten Konstrukteure verwenden std::unique_ptr wie die anderen Smart-Pointer-Typen der Lage sein, die ein std::unique_ptr nehmen. Wenn Sie eine interne Liste solcher Ressourcen verwalten, sollten Sie wahrscheinlich std::shared_ptr verwenden.

Verwandte Themen