Tengo una clase que acumula información sobre un conjunto de objetos y puede actuar como un funtor o como un iterador de salida. Esto me permite hacer cosas como:Impedir copias innecesarias de los objetos del functor C++
std::vector<Foo> v;
Foo const x = std::for_each(v.begin(), v.end(), Joiner<Foo>());
y
Foo const x = std::copy(v.begin(), v.end(), Joiner<Foo>());
Ahora, en teoría, el compilador debe ser capaz de utilizar el copy elision and return-value optimizations por lo que sólo un único Joiner
objeto necesita ser creado. En la práctica, sin embargo, la función hace una copia sobre la cual operar y luego copia eso de vuelta al resultado, incluso en versiones completamente optimizadas.
Si creo el funtor como un valor-I, el compilador crea dos copias extra en lugar de uno:
Joiner<Foo> joiner;
Foo const x = std::copy(v.begin(), v.end(), joiner);
Si torpemente fuerzo el tipo de plantilla a una referencia que pasa una referencia, pero luego hace una copia de todos modos y devuelve una referencia que cuelga a la (ahora destruido) copia temporal:
x = std::copy<Container::const_iterator, Joiner<Foo>&>(...));
que puede hacer las copias baratas utilizando una referencia al estado en lugar del propio estado en el funtor en el estilo de std::inserter
, lo que lleva a algo ing así:
Foo output;
std::copy(v.begin(), v.end(), Joiner<Foo>(output));
Pero esto hace que sea imposible utilizar el estilo "funcional" de los objetos inmutables, y en general no es tan agradable.
¿Hay alguna forma de alentar al compilador a eludir las copias temporales, o hacer que pase una referencia hasta el final y devolver esa misma referencia?
Lo beneficioso o posible de RVO depende probablemente de su definición de 'Joiner'. Dicho esto, ¿estás realmente dispuesto a renunciar a la sintaxis simple y limpia 'Foo const x = std :: for_each (v.begin(), v.end(), Joiner());' con algo posiblemente mucho más feo? –
GManNickG
for_each/copy debería devolver un Joiner, no un Foo, ¿verdad? Tu ejemplo me confunde. A menos que esté tratando de implicar que Joiner es convertible a Foo? –
Escribí tres respuestas diferentes para demostrar que estás equivocado y finalmente entendí que no. Muy útil, gracias por la pregunta. +1. –