2010-09-15 10 views
22

¿Es posible devolver un contenedor estándar desde una función sin hacer una copia?Devolviendo un C++ std :: vector sin una copia?

código Ejemplo:

std::vector<A> MyFunc(); 

... 

std::vector<A> b = MyFunc(); 

Por lo que yo entiendo, esto copia el valor de retorno en un nuevo vector b. ¿Hacer que la función devuelva referencias o algo así permite evitar la copia?

+0

Duplicado de http://stackoverflow.com/questions/3703302/c-vector-return-vs-parameter/3703325#3703325? –

Respuesta

25

Si su compilador es compatible con el NRVO, no se realizará ninguna copia, siempre que se cumplan ciertas condiciones en la función que devuelve el objeto. Afortunadamente, esto finalmente se agregó en Visual C++ 2005 (v8.0) Esto puede tener un impacto importante en el rendimiento si el contenedor es grande, obviamente.

Si su propio compilador no dice si es compatible o no, debería poder compilar el código C++ al ensamblador (en modo optimizado/versión) y verificar lo que se hace usando una función de muestra simple.

También hay una excelente discusión más amplia here

+0

Gracias! Alguna idea sobre NRVO en gcc? –

+0

@static_rtti - Tendré que ceder a la gente de Linux por eso, por miedo a meterme en la boca –

+0

Puedes hacer pruebas fácilmente con una clase que rastree en Copy CTor. Tenga en cuenta que esta es una optimización "puede ser", que no necesariamente funcionará, p. con objetos de retorno con nombre diferente. Sin embargo, con las referencias de C++ 0x rvalue, las clases pueden implementar una garantía. Puede esperar esto para contenedores estándar en un STL actualizado. – peterchen

2

Si se puede modificar la firma de la función, puede utilizar

std::vector<A>& MyFunc(); 

o

void MyFunc(std::vector<A>& vect); 

Usted también podría devolver un puntero inteligente , pero eso implica renovar el objeto.

some_smart_pointer<std::vector<A>> MyFunc(); 

HTH

+4

Es probable que la primera no funcione si está devolviendo un vector que es local en la función. El segundo está bien aunque – jcoder

+3

@John Burton/@ beezler - 'no va a funcionar' es decirlo suavemente, suponiendo que el contenedor devuelto esté basado en la pila en la función llamada. –

13

rvalues ​​("temporales") unidos a const referencias tendrán su tiempo de vida extendido hasta el final de la vida de la referencia. Así que si usted no necesita modificar ese vector, lo siguiente será hacer:

const std::vector<A>& b = MyFunc(); 

si necesita modificar el vector, simplemente codificar de la manera que es más fácil de leer hasta que tengamos pruebas (que se obtiene a través perfilado) que esta línea incluso importa en cuanto al rendimiento.

De lo contrario, confíe en C++ 1x con sus referencias rvalue y la semántica de movimiento que viene "muy pronto" y optimizando esa copia sin tener que hacer nada.

Cuestiones relacionadas