Si desea rendimiento, pase por valor si lo está almacenando.
Supongamos que tiene una función llamada "ejecutar esto en el hilo de la interfaz de usuario".
std::future<void> run_in_ui_thread( std::function<void()> )
que ejecuta un código en el subproceso "ui", luego señala el futurecuando está hecho. (Útil en los marcos de la interfaz de usuario donde el hilo de la interfaz de usuario es donde se supone que debes jugar con los elementos de la interfaz de usuario)
Tenemos dos firmas que estamos considerando:
std::future<void> run_in_ui_thread( std::function<void()> ) // (A)
std::future<void> run_in_ui_thread( std::function<void()> const& ) // (B)
Ahora, es probable que usemos estos de la siguiente manera:
run_in_ui_thread( [=]{
// code goes here
} ).wait();
que creará un cierre anónimo (una lambda), construirá un std::functionfuera de él, lo pasará a la run_in_ui_threadfunción y luego esperará a que termine de ejecutarse en el hilo principal.
En el caso (A), std::functionse construye directamente a partir de nuestra lambda, que luego se utiliza dentro de run_in_ui_thread. La lambda se moveintroduce en el std::function, por lo que cualquier estado móvil se transporta de manera eficiente.
En el segundo caso, std::functionse crea un temporal , se moveintroduce el lambda en él, luego ese temporal std::functionse usa como referencia dentro del run_in_ui_thread.
Hasta ahora, todo bien: los dos se desempeñan de manera idéntica. ¡Excepto run_in_ui_threadque va a hacer una copia de su argumento de función para enviar al hilo ui para ejecutar! (regresará antes de terminar con él, por lo que no puede simplemente usar una referencia a él). Para el caso (A), simplemente moveel std::functionen su almacenamiento a largo plazo. En el caso (B), nos vemos obligados a copiar el std::function.
Esa tienda hace que pasar por valor sea más óptimo. Si existe alguna posibilidad de que esté almacenando una copia del std::functionpase por valor. De lo contrario, de cualquier manera es más o menos equivalente: el único inconveniente del std::functionsub -valor es si está tomando el mismo voluminoso y tiene un método secundario tras otro. Salvo eso, a moveserá tan eficiente como a const&.
Ahora, hay algunas otras diferencias entre los dos que se aplican principalmente si tenemos un estado persistente dentro del std::function.
Suponga que std::functionalmacena algún objeto con a operator() const, pero también tiene algunos mutablemiembros de datos que modifica (¡qué grosero!).
En el std::function<> const&caso, los mutablemiembros de datos modificados se propagarán fuera de la llamada a la función. En el std::function<>caso, no lo harán.
Este es un caso de esquina relativamente extraño.
Desea tratar std::functioncomo lo haría con cualquier otro tipo posiblemente pesado y de bajo costo. Mudarse es barato, copiar puede ser costoso.
sizeof(std::function)no ser más que2 * sizeof(size_t), que es el tamaño mínimo que alguna vez consideraría para una referencia constante.