Griffe haben eine andere richtige Semantik als Zeiger. Also für mich ein Beispiel wie dieses (aus der Nullregel):
class module {
public:
explicit module(std::wstring const& name)
: handle { ::LoadLibrary(name.c_str()), &::FreeLibrary } {}
// other module related functions go here
private:
using module_handle = std::unique_ptr<void, decltype(&::FreeLibrary)>;
module_handle handle;
};
verwenden unique_ptr
als „Ownership-in-a-Package“ für Griffe ist ein schlechtes Beispiel. Erstens nutzt es das interne Wissen, dass das Handle ein Zeigertyp ist, und verwendet dies, um a zu erstellen unique_ptr
auf den Grundtyp baut der Grifftyp „blickdicht“ auf.
Handles können von jedem Typ sein, sie können ein Zeiger sein, sie können ein Index sein oder wer weiß. Am wichtigsten ist, dass Sie (von den meisten C-APIs zum Beispiel) ein Handle und seine Ressourcenfreigabefunktion zur Hand haben.
Gibt es dafür ein richtiges „Ownership-in-a-Package“. funktioniert in Handle-Semantik? Ich meine, bereits öffentlich verfügbar, damit man es verwenden kann?
Für mich, unique_ptr
et. Al. nicht funktioniert, muss ich unnötige Annahmen über den Handle-Typ treffen istwenn ich nur durch den undurchsichtigen Grifftyp und seine Freigabefunktion nur ein “Eigentum an einem Paket” erhalten möchte.
Es macht keinen Sinn, in den Handle-Typ zu blicken, um Konstruktionen auf dieser Information zu erstellen. Es ist ein Griff, es sollte keine Rolle spielen.
Ich werde hier die Gefühle eines anderen SO-Benutzers in der Antwort einer anderen Frage zitieren:
Erstellen Sie eine bestimmte “Smart Pointer” -Klasse, das dauert nicht lange. Missbrauche den Bibliotheksunterricht nicht. Handle-Semantik unterscheidet sich stark von der eines C++-Zeigers; Zum einen macht die Dereferenzierung eines HANDLE keinen Sinn.
Ein weiterer Grund, eine benutzerdefinierte Smart-Handle-Klasse zu verwenden – NULL bedeutet nicht immer ein leeres Handle. Manchmal ist es INVALID_HANDLE_VALUE, was nicht dasselbe ist.
Haftungsausschluss:
Diese Frage formuliert diese neu und baut darauf auf:
- Wo ist die richtige (Ressourcenhandhabung) Rule of Zero?
Ich bin mit Ihrer Prämisse nicht einverstanden.
unique_ptr
ist vielleicht eine leichte Fehlbezeichnung – es handhabt Ressourcen. EINHANDLE
kümmert sich auch um Ressourcen. Dies ist eine perfekte Übereinstimmung.– Konrad Rudolf
14. Februar 2013 um 15:27 Uhr
Ich stütze meine Prämissen nicht nur auf den Typnamen …
– pfeffer_chico
14. Februar 2013 um 15:29 Uhr
Was ist genau dein problem? Der Name gefällt dir nicht
unique_ptr
?– Etienne de Martell
14. Februar 2013 um 15:32 Uhr
@ EtiennedeMartel: Zu verwenden
unique_ptr
Für ein Nicht-Zeiger-Handle benötigen Sie einen speziellen Löscher, der eine Verschachtelung definiertpointer
Typ, und daspointer
Typ kann nicht einfach sein, sagen wir,int
seitint
entspricht nicht den NullablePointer-Anforderungen, dieunique_ptr
will. Jedoch, Sie können einen einfachen Wrapper schreiben das passt sich an irgendetwas zu diesen Nullable-Pointer-Anforderungen. Wenn Sie möchten, können Sie auch ein Unär hinzufügenoperator*
das leitet weiter*value
und einoperator->
damit du es wirklich verwenden kannst*up
undup->foo()
.– Xeo
14. Februar 2013 um 15:34 Uhr
@Xeo: Wenn Sie sich die Mühe machen, diesen Wrapper zu schreiben … warum schreiben Sie nicht einfach ein richtiges RAII-Objekt, das einen beliebigen Wert enthalten kann, und rufen eine bestimmte Funktion / einen bestimmten Funktor für diesen Typ auf, wenn er zerstört wird? Es ist verdammt viel weniger stumpf als mit
unique_ptr
für Nicht-Zeiger-Dinge. Im Ernst, Schreiben von Copy/Move-Konstruktoren für ein Objekt ist kaum eine lästige Belastung.– Nicol Bolas
15. Februar 2013 um 3:23 Uhr