Cuántos datos se copian, cuando se devuelve un std :: vector en una función y qué tan grande será la optimización para colocar el std :: vector en free-store (en el montón) y devolver un puntero en su lugar, es decir, es:
std::vector *f()
{
std::vector *result = new std::vector();
/*
Insert elements into result
*/
return result;
}
más eficiente que:
std::vector f()
{
std::vector result;
/*
Insert elements into result
*/
return result;
}
?
c++
return-value
stdvector
Morten
fuente
fuente
f
?Respuestas:
En C ++ 11, esta es la forma preferida:
Es decir, retorno por valor.
Con C ++ 11,
std::vector
tiene movimiento semántica, lo que significa el local de vector declarado en su función se trasladó a la entrega y en algunos casos incluso el movimiento puede ser elidido por el compilador.fuente
return std::move(v);
desactivará la elisión de movimiento incluso si fue posible con soloreturn v;
. Por lo que se prefiere este último.Debería devolver por valor.
El estándar tiene una característica específica para mejorar la eficiencia de la devolución por valor. Se llama "copia elisión", y más específicamente en este caso la "optimización del valor de retorno con nombre (NRVO)".
Los compiladores no tienen que implementarlo, pero de nuevo los compiladores no tienen que implementar la función de alineación (o realizar ninguna optimización). Pero el rendimiento de las bibliotecas estándar puede ser bastante pobre si los compiladores no optimizan, y todos los compiladores serios implementan inlining y NRVO (y otras optimizaciones).
Cuando se aplica NRVO, no habrá copia en el siguiente código:
Pero el usuario puede querer hacer esto:
Copiar la elisión no impide una copia aquí porque es una asignación en lugar de una inicialización. Sin embargo, aún debe devolver por valor. En C ++ 11, la asignación se optimiza mediante algo diferente, llamado "semántica de movimiento". En C ++ 03, el código anterior causa una copia, y aunque en teoría un optimizador podría evitarlo, en la práctica es demasiado difícil. Entonces
myvec = f()
, en lugar de , en C ++ 03 debes escribir esto:Existe otra opción, que es ofrecer una interfaz más flexible al usuario:
Luego, también puede admitir la interfaz existente basada en vectores además de eso:
Esto podría ser menos eficiente que su código existente, si su código existente se usa
reserve()
de una manera más compleja que solo una cantidad fija por adelantado. Pero si su código existente básicamente llamapush_back
al vector repetidamente, entonces este código basado en plantillas debería ser tan bueno.fuente
Es hora de que publique una respuesta sobre RVO , yo también ...
Si devuelve un objeto por valor, el compilador a menudo lo optimiza para que no se construya dos veces, ya que es superfluo construirlo en la función como temporal y luego copiarlo. Esto se denomina optimización del valor de retorno: el objeto creado se moverá en lugar de copiarse.
fuente
Un modismo común anterior a C ++ 11 es pasar una referencia al objeto que se está completando.
Entonces no hay copia del vector.
fuente
Si el compilador admite la optimización de valor devuelto con nombre ( http://msdn.microsoft.com/en-us/library/ms364057(v=vs.80).aspx ), puede devolver directamente el vector siempre que no haya:
NRVO optimiza las llamadas redundantes al constructor y destructor de copias y, por lo tanto, mejora el rendimiento general.
No debería haber una diferencia real en tu ejemplo.
fuente
Y si desea imprimirlo en main (), debe hacerlo en un bucle.
fuente
Por más agradable que pueda ser el "retorno por valor", es el tipo de código que puede llevar a uno a error. Considere el siguiente programa:
El programa erróneo anterior indicará que no hay errores incluso si se utilizan las opciones de informes GNU g ++ -Wall -Wextra -Weffc ++
Si debe producir un valor, lo siguiente funcionaría en lugar de llamar a vecFunc () dos veces:
Lo anterior tampoco produce objetos anónimos durante la iteración del bucle, pero requiere una posible operación de copia (que, como algunos señalan, podría optimizarse en algunas circunstancias. Pero el método de referencia garantiza que no se producirá ninguna copia. Creer que el compilador realizar RVO no sustituye a intentar construir el código más eficiente que puedas. Si puedes discutir la necesidad de que el compilador haga RVO, estás por delante del juego.
fuente
fuente