2016-08-30 3 views
0

Ich habe eine Klasse durch Belichtung ist Schnittstelle Add-Funktion:Schnittstellenfunktion rvalue Zeiger immer Shared_ptr zu initialisieren

void AddObject(Object *o); 

Innerhalb der Klasse halte ich die Objekte in set<shared_ptr<Object>>. Da ich aus dem empfangenen Zeiger shared_ptr erstellen werde, dachte ich, das Funktionsargument auf nur Rvalue-Zeiger zu beschränken, um sicherzustellen, dass der Benutzer den Zeiger nicht lösche, den ich verwende. Und so werde ich die Funktionsdeklaration ändern:

void AddObject(Object* &&o); 

so eine typische Anwendung sind:

AddObject(new Object()) 

den Benutzer verhindert versehentlich Zeiger löschen Ich halte. Ich möchte nicht shared_ptr in der Schnittstelle verwenden, weil der Benutzer nicht mit shared_ptr vertraut ist. Glaubst du, dass mein Vorschlag eine gute Idee ist?

+0

Was ist falsch mit einem 'std :: unique_ptr'? – AndyG

+0

Nun die gleiche Frage gilt, wenn ich unique_ptr stattdessen verwendet –

+0

Ich denke, "unique_ptr" macht es ein wenig offensichtlicher in der Schnittstelle, was Sie erwarten. Darüber hinaus geht die 'move'-Semantik bereits mit der Übergabe einher, also ist es natürlich,' std :: move' ein 'unique_ptr', aber wirklich seltsam zu' std :: move' einen rohen Pointer. – AndyG

Antwort

0

Ich denke, das ist eine schlechte Idee. Ich bin mir sicher, dass es einen Grund gibt, warum shared_ptr c-tor, der einen rohen Pointer erhält, explizit markiert wird, anstatt r-value zu verwenden. In meinen Augen ist es besser, die Benutzer zu lehren einmal über intelligente Zeiger oder zumindest lehrt sie über make_shared/make_unique mit (die sind sicherer und, im Fall von make_shared, effizienten, BTW).

BTW, warum shared_ptr und nicht unique_ptr?

Auch, warum set? Auch wenn Sie sicherstellen möchten, dass Sie jeden Zeiger nur einmal gedrückt halten und ein vector jedes Mal nicht natürlich genug in Ihrem Code suchen, sehe ich keinen Grund, die Zeiger sortiert statt unordered_set zu halten.

0

Vor allem dieser Ansatz wird der Benutzer das Löschen der Zeiger nicht verhindern. Betrachten Sie dieses Beispiel

auto obj = new Object(); 
    AddObject(std::move(obj)); 
    delete obj; 

Zweitens ist die Anzahl der Schritte zwischen new Aufruf und die Schaffung von shared_ptr sollte so gering wie möglich sein. Wenn innerhalb von AddObject etwas passiert, bevor ein shared_ptr erstellt werden kann, wird das Objekt niemals gelöscht.

Gleiches gilt, wenn es mehr Argumente AddObject() sind. Wenn das Erstellen fehlschlägt, werden Sie Speicher verlieren.

void AddObject(Object* &&o, SomeOtherObject* x); 

    AddObject(new Object(), xx()); // if xx() throws, memory leak will occur 

Im Idealfall würden Sie "wrap" Objekt in shared_ptr Konstruktion zu schaffen:

void AddObject(std::shared_ptr<Object> o); 

    AddObject(std::make_shared<Object>()); 
+0

Ihr erstes Beispiel zeigt in der Tat, wie Benutzer bereitgestellten Zeiger löschen kann, aber es ist so explizit, dass nur böse Benutzer es tun werden. –

0

eine der folgenden Methoden kann Ihr Problem lösen.

  1. Sie können weitere Kommentare für AddObject anfügen, um Benutzern mitzuteilen, dass der von ihnen hinzugefügte Zeiger nicht zulässig ist. Das ist fast genug.
  2. Oder Sie können auch Object erben von einer Basisklasse, die eine private Destruktor und eine Methode namens destroyByOwner hat.
Verwandte Themen