Vermeiden Sie es, by-reference Argument zurückzugeben

8

Angenommen, ich habe eine Klasse Option :

%Vor%

Das an Option::getOrElse übergebene Argument ist der Standardwert, der zurückgegeben werden soll, wenn Option leer ist:

%Vor%

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.

    
Zizheng Tai 03.05.2016, 00:21
quelle

4 Antworten

4
  

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.

    
Barry 03.05.2016 00:50
quelle
0

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.

    
Michael Burr 03.05.2016 01:14
quelle
0

Ich möchte lieber als Referenz zurückkommen und den Anrufer entscheiden lassen, ob er eine Referenz oder eine Kopie des zurückgegebenen Wertes speichern möchte.

    
MikeMB 04.05.2016 07:27
quelle
0

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:

  1. gibt einen gültigen Zeiger oder
  2. zurück
  3. throw bad_alloc Ausnahme; Es wird nicht null zurückgegeben

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%     
dhCompiler 04.05.2016 07:12
quelle

Tags und Links