No. La mejor práctica es directamente return t;
.
En caso T
clase tiene mover el constructor no se eliminan, y el aviso t
es una variable local que return t
es elegible para la copia elisión, construcciones que se mueva el objeto devuelto al igual que lo hace return std::move(t);
. Sin embargo, return t;
sigue siendo elegible para copiar/mover elisión, por lo que la construcción puede omitirse, mientras que return std::move(t)
siempre construye el valor de retorno utilizando el constructor de movimientos.
En caso de movimiento del constructor en la clase T
se elimina pero constructor de copia disponible, return std::move(t);
no se compilará, mientras que todavía return t;
compila utilizando constructor de copia. A diferencia de @Kerrek mencionado, t
no está vinculado a una referencia rvalue. Hay una resolución de sobrecarga de dos etapas para los valores de retorno que son elegibles para la elisión de copia: intente mover primero, luego copie, y tanto mover como copiar posiblemente se eliminen.
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
}
Si la expresión es return
lvalue y no es elegible para la copia elisión (muy probablemente va a devolver una variable no local o expresión valor-I) y todavía se desea evitar la copia, std::move
será útil. Pero tenga en cuenta que la mejor práctica es hacer que la elisión de copia sea posible.
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) en el estándar describe el proceso.
12,8 [class.copy]
32 Cuando se cumplen los criterios para la elisión de una operación de copia o se cumplirían, salvo por el hecho de que el objeto de origen es un parámetro de función, y el objeto a ser copiado se designa con un lvalue, la resolución de sobrecarga para seleccionar el constructor para la copia se realiza primero como si el objeto fuera designado por un valor r. Si la resolución de sobrecarga falla, o si el tipo del primer parámetro del constructor seleccionado no es una referencia rvalue al tipo del objeto (posiblemente cv-qualified), la resolución de sobrecarga se realiza nuevamente, considerando el objeto como un valor l. [Nota: esta resolución de sobrecarga de dos etapas se debe realizar independientemente de si se producirá elisión de copia. Determina el nombre del constructor que se invocará si no se realiza una elisión, y el constructor seleccionado debe estar accesible incluso si se elimina la llamada. nota -fin]
[aquí] (http://stackoverflow.com/questions/9827183/why-am-i-allowed-to-copy-unique-ptr) es una pregunta similar –
[FAQ relacionado] (http://stackoverflow.com/a/11540204/252000) – fredoverflow