No. La procedura consigliata è direttamente return t;
.
In caso classe T
ha spostare costruttore non eliminati, e l'avviso t
è una variabile locale che return t
è idoneo per la copia elisione, muovere costrutti l'oggetto restituito, proprio come return std::move(t);
fa. Tuttavia return t;
è ancora idoneo a copiare/spostare elision, quindi la costruzione può essere omessa, mentre return std::move(t)
costruisce sempre il valore di ritorno usando il costruttore di mosse.
Nel caso in cui il costruttore di movimento nella classe T
sia eliminato ma il costruttore di copia sia disponibile, return std::move(t);
non verrà compilato, mentre return t;
compila ancora utilizzando il costruttore di copie. A differenza di @Kerrek menzionato, t
non è associato a un riferimento di rvalue. Esiste una risoluzione di sovraccarico a due stadi per i valori di ritorno idonei per l'elisione di copia: provare prima a muovere, quindi copiare, ed entrambi possono essere spostati e copiati.
class T
{
public:
T() = default;
T (T&& t) = delete;
T (const T& t) = default;
};
T foo()
{
T t;
return t; // OK: copied, possibly elided
return std::move(t); // error: move constructor deleted
return static_cast<T&>(t); // OK: copied, never elided
}
Se l'espressione return
è lvalue e non ammissibili per la copia elision (molto probabilmente si restituisce una variabile non locale o l'espressione lvalue) e ancora volete evitare la copia, std::move
saranno utili. Ma tieni a mente che la pratica migliore è la possibilità di fare copia elision.
class T
{
public:
T() = default;
T (T&& t) = default;
T (const T& t) = default;
};
T bar(bool k)
{
T a, b;
return k ? a : b; // lvalue expression, copied
return std::move(k ? a : b); // moved
if (k)
return a; // moved, and possibly elided
else
return b; // moved, and possibly elided
}
12.8 (32) nella norma descrive il processo.
12,8 [class.copy]
32 Quando i criteri di elisione un'operazione di copia sono soddisfatte o sarebbero soddisfatte tranne che per il fatto che l'oggetto di origine è un parametro funzione, e l'oggetto da essere copiato è designato da un lvalue, la risoluzione di sovraccarico per selezionare il costruttore per la copia viene prima eseguita come se l'oggetto fosse designato da un valore di rvalue. Se la risoluzione del sovraccarico non riesce, o se il tipo del primo parametro del costruttore selezionato non è un riferimento di valore al tipo dell'oggetto (possibilmente qualificato cv), la risoluzione di sovraccarico viene eseguita di nuovo, considerando l'oggetto come un lvalue. [Nota: questa risoluzione di sovraccarico a due stadi deve essere eseguita indipendentemente dal fatto che si verifichi l'elisione della copia. Determina il costruttore da chiamare se elision non viene eseguito e il costruttore selezionato deve essere accessibile anche se la chiamata viene eliminata. -end nota]
[qui] (http://stackoverflow.com/questions/9827183/why-am-i-allowed-to-copy-unique-ptr) è una domanda simile –
[FAQ relative] (http://stackoverflow.com/a/11540204/252000) – fredoverflow