todas tipos las funciones ejemplos comandos caracteristicas c++ stl c++11 move-semantics return-value-optimization

tipos - Modo correcto(semántica de movimiento) para devolver un std:: vector de llamadas a funciones en C++ 11



tipos de funciones en c (3)

Creo que (1) y (2) tienen un rendimiento idéntico incluso sin C ++ 0x, siempre y cuando su compilador realice la Optimización del valor de retorno con nombre, que creo que la mayoría hace. Ninguno de los dos debe hacer copias ni movimientos .

Por favor corrígeme si me equivoco, porque si es así no entiendo bien a NRVO.

Quiero llenar std :: vector (o algún otro contenedor STL):

class Foo { public: Foo(int _n, const Bar &_m); private: std::vector<Foo> fooes_; }

1. Buen aspecto ctor, rendimiento caro

std::vector<Foo> get_vector(int _n, const Bar &_m) { std::vector<Foo> ret; ... // filling ret depending from arguments return ret; } Foo::Foo(int _n, const Bar &_m) : fooes_(get_vector(_n, _m) {}

2. Mejor rendimiento, peor aspecto ctor

void fill_vector(int _n, const Bar &_m, std::vector<Foo> &_ret) { ... // filling ret depending from arguments } Foo::Foo(int _n, const Bar &_m) { fill_vector(_n, _m, fooes_); }

¿Es posible reescribir la función get_vector desde el primer ejemplo con C ++ 0x (funciones de semántica de movimiento, etc.) para evitar la copia redundante y las llamadas de constructor?


En el caso particular que está considerando, la primera implementación es tan eficiente como la segunda. El compilador optimizará la copia de ret en la función get_vector hasta el valor de retorno, y usará la semántica de movimiento para transferir la propiedad del vector a la clase contenedora. Mover construcción en un vector requiere (depende de la implementación, pero una buena aproximación es) 3 copias de puntero, independientemente del número y tamaño de los elementos en el contenedor. Pasar el vector como referencia para modificar requiere una única copia del puntero (costo aproximado de nuevo), pero cualquier operación que realice en el vector dominará el costo de cualquiera de las opciones.

Hay algunas circunstancias muy específicas cuando pasar un vector en una función para la modificación puede ser más rápido, pero esas son raras y están más relacionadas con el dominio que con el vector en sí. Simplemente ignore eso, codifique primero para la mantenibilidad, y si el programa es lento, determine el perfil donde se encuentra el costo del programa, y ​​solo entonces piense en optimizarlo. La parte interesante es que una vez que ha perfilado, probablemente sepa cuál es el cuello de botella y eso significa que tendrá pistas sobre qué cambiar.


Si está utilizando un compilador compatible con C ++ 0x y una biblioteca estándar, obtendrá un mejor rendimiento del primer ejemplo sin hacer nada . El valor de retorno de get_vector(_n, _m) es temporal, y el constructor de movimiento para std::vector (un constructor que toma una referencia rvalue) se llamará automáticamente sin más trabajo por su parte.

En general, los escritores que no sean bibliotecarios no necesitarán usar referencias rvalue directamente; obtendrá una buena porción de los beneficios automáticamente.