Angenommen, ich habe eine Klasse Option
:
Das an Option::getOrElse
übergebene Argument ist der Standardwert, der zurückgegeben werden soll, wenn Option
leer ist:
Ich glaube jedoch, dass der folgende Code nicht sicher ist:
%Vor% Ein sicherer Weg wäre, nach Wert von Option::getOrElse
zurückzukehren, aber das wäre verschwenderisch, wenn Option
nicht leer ist. Kann ich das irgendwie umgehen?
UPDATE: Ich denke darüber nach, vielleicht den Argumenttyp (lvalue / rvalue) von getOrElse
zu überladen, habe aber nicht genau herausgefunden, wie das geht.
UPDATE 2: Vielleicht?
%Vor%Aber ich denke, dass dies mehrdeutig sein könnte, da beide lvalue und rvalue Argumente die zweite Version passen.
Ich glaube jedoch, dass der folgende Code nicht sicher ist:
%Vor%
Sie haben Recht. Deshalb gibt std::optional::value_or()
eine T
und keine T&
oder T const&
zurück. Gemäß der Begründung in N3672 :
Es wurde argumentiert, dass die Funktion eher durch einen konstanten Verweis als durch einen Wert zurückgegeben werden sollte, was in bestimmten Situationen den Kopieraufwand vermeiden würde:
%Vor%Der Vorteil der Funktion value_or ist jedoch nur sichtbar, wenn das optionale Objekt als temporäres Objekt (ohne den Namen) bereitgestellt wird. Ansonsten ist ein ternärer Operator genauso nützlich:
%Vor%Auch die Rückgabe als Referenz würde wahrscheinlich eine hängende Referenz darstellen, falls das optionale Objekt deaktiviert wird, weil das zweite Argument normalerweise ein temporäres ist:
%Vor%
Ich schlage vor, dass Sie die gleichen Richtlinien befolgen. Wenn Sie die Kopie wirklich vermeiden müssen, verwenden Sie eine Ternärdatei. Dies ist sicher und kopierfrei:
%Vor% Wenn Sie das wirklich nicht tun oder das Optional
sowieso ein rval ist, ist getOrElse()
prägnanter.
Da Benutzer Ihrer Klasse erwarten können, dass die von Option::get()
zurückgegebene Referenz nur so lange gültig ist wie die bestimmte Instanz der Option
-Objektlebensdauer, können Sie vernünftigerweise die gleiche Erwartung für das abgeben, was von% co_de zurückgegeben wird %.
In diesem Fall könnte es ein akzeptabler Overhead für das Objekt sein, eine Sammlung von Dingen zu pflegen, die es für den Client am Leben erhalten muss:
%Vor% Die von Option::getOrElse()
zurückgegebenen Referenzen sind so lange gültig, wie der von Option::getOrElse()
zurückgegebene Verweis lautet. Das bedeutet natürlich auch, dass Option::get()
eine Ausnahme auslösen kann.
Als kleine Verbesserung, wenn der Option::getOrElse()
-Typ als Schlüssel für einen assoziativen Container verwendet werden kann, können Sie einen von diesen anstelle von T
verwenden und das Speichern von Duplikaten einfach vermeiden.
Kann ich vorschlagen, diesen Kurs neu zu gestalten?
Es hat einen Standard-ctor, der das val_ auf nullptr belassen kann, aber gleichzeitig eine get () hat, die wegen der Dereferenz (*) eine Ausnahme auslösen kann. Es wurde auch entworfen, um T in shared_prt zu speichern, aber als Referenz zurückzugeben.
Lassen Sie den Client wissen, dass es null ist:
%Vor%Der Client-Code wurde geändert von:
%Vor%zu sein:
%Vor%Warum lösche ich: if (val_ == nullptr) {
Machen wir make_shared & lt; & gt; klar:
So ist IsNull () auch nutzlos, es sollte wie folgt aussehen:
%Vor%Warum shared_ptr verwenden? Optionsobjekte können mehrmals verschoben oder kopiert werden? oder ich ziehe es vor, es wie folgt zu gestalten:
%Vor%