c++ - ¿Cómo usar la semántica de movimiento con std:: string durante el retorno de la función?
c++11 move-semantics (3)
No hay necesidad de decir return std::move(str);
si str
es una variable local: si la variable satisface los criterios para la optimización del valor de retorno, en una declaración de return
la variable se unirá a una referencia de valor nominal.
Además, tenga en cuenta que probablemente no debería devolver una referencia a una variable local, ni lvalue ni rvalue reference.
Dicho todo, deberías tener:
int foo() { int x; /*...*/ return x; }
std::string bar() { std::string str; /*...*/ return str; }
Posible duplicado:
C ++ 11 rvalores y movimiento semántico confusión.
Lo que creo que es correcto es
std::string GetLine()
{
std::string str;
std::getline(std::cin, str);
return std::move(str);
}
Pero en este enlace http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html (verifique la parte del encabezado Cómo devolver una referencia-valor explícita desde un función)
que es el hit número 1 de búsqueda de google para semánticas de movimiento muestra una función similar a la firma como
int&& GetInt()
{
int x = 0;
// code here
return std::move(x);
}
De lo que leí en otros lugares, && significa una referencia de valor así que en este caso está devolviendo una referencia a un objeto que no existe.
Entonces, ¿cuál es?
(Sí, sé que mover un int no tiene ningún beneficio real, pero la pregunta es si usar el tipo de retorno de std :: string o std :: string && en la primera función. Y si así es como debería hacerse para todos los tipos).
Respondiendo a la pregunta, tipo de: devolver una string
. No move
nada, sino que utilice (confíe en) RVO:
std::string func()
{
std::string rv;
/* ... */
return rv;
}
Así es como generalmente se debe hacer. No puede devolver una referencia (valor r o no) a un temporal.
Usted tiene toda la razón de que el ejemplo int&& GetInt()
es incorrecto y está devolviendo una referencia a un objeto destruido. Sin embargo, a menos que me lo haya perdido, el enlace que publicaste no muestra ningún código que devuelva una referencia a una variable local . En cambio, veo una referencia a una variable global que se devuelve, lo cual está bien.
Aquí es cómo se usa la semántica de movimiento al regresar:
std::string func()
{
std::string rv;
/* ... */
return rv;
}
Por lo general, no debe usar std::move()
al devolver un objeto. La razón de esto es que el movimiento ya está permitido de manera implícita en cualquier momento en que se produzca RVO, y el uso de std::move()
suprimirá el RVO. Por lo tanto, usar std::move()
nunca será mejor y con frecuencia será peor que simplemente regresar normalmente.
Nuevamente, usar std::move()
puede ser peor que simplemente nombrar la variable que se devolverá porque suprime la optimización del valor de retorno. La optimización del valor de retorno permite que un objeto se devuelva a la persona que llama sin necesidad de copiar ese objeto
en una declaración de
return
en una función con un tipo de retorno de clase, cuando la expresión es el nombre de un objeto automático no volátil (que no sea un parámetro de función o cláusula catch) con el mismo tipo no calificado cv que el tipo de retorno de función, la operación de copiar / mover se puede omitir construyendo el objeto automático directamente en el valor de retorno de la función- [class.copy] 12.8 / 31
Pero el uso de std::move()
evita que la expresión de retorno sea el nombre del objeto que está devolviendo. En cambio, la expresión es más complicada y ya no se permite que el lenguaje le dé un manejo especial.
La razón por la que simplemente nombrar el objeto no es peor que usar std::move()
es porque hay otra regla que dice que una expresión ya puede tratarse como un valor r sin necesidad de std::move()
.
Cuando los criterios para la elección de una operación de copia se cumplen o se cumplirían, salvo por el hecho de que el objeto de origen es un parámetro de función, y el objeto que se va a copiar se designa mediante un lvalor, la resolución de sobrecarga para seleccionar el constructor para la copia es Primero se realiza como si el objeto fuera designado por un valor de r.