Je ne comprends pas quand je dois utiliser std::move
et quand je dois laisser le compilateur optimiser... par exemple :
using SerialBuffer = vector< unsigned char >;
// let compiler optimize it
SerialBuffer read( size_t size ) const
{
SerialBuffer buffer( size );
read( begin( buffer ), end( buffer ) );
// Return Value Optimization
return buffer;
}
// explicit move
SerialBuffer read( size_t size ) const
{
SerialBuffer buffer( size );
read( begin( buffer ), end( buffer ) );
return move( buffer );
}
Lequel dois-je utiliser ?
0 votes
D'après ce que j'ai lu jusqu'à présent, le consensus général semble compter sur le fait que le compilateur utilise RVO au lieu de
move
explicitement : les compilateurs modernes sont suffisamment intelligents pour utiliser le RVO presque partout et il est plus efficace que le RVO.move
. Mais ce ne sont que des "ouï-dire", alors je suis tout à fait intéressé par une explication documentée.12 votes
Vous n'avez jamais besoin de déplacer explicitement la valeur de retour d'une fonction de variable locale. C'est un déplacement implicite.
3 votes
Le compilateur est alors libre de choisir : Si c'est possible, il utilisera RVO et si ce n'est pas le cas, il peut toujours faire un déplacement (et si aucun déplacement n'est possible pour le type, alors il fera une copie).
0 votes
Pour ce que je sais, le compilateur ne peut pas faire de déplacement dans la première version parce que le tampon est une valeur l, il a un nom et aucun constructeur de déplacement ne sera appelé.
5 votes
@MartinBa, il ne faut jamais dire jamais ;) Vous avez besoin d'un déplacement explicite si la variable locale n'est pas du même type que le type de retour, par ex.
std::unique_ptr<base> f() { auto p = std::make_unique<derived>(); p->foo(); return p; }
mais si les types sont les mêmes, il se déplacera si possible (et ce déplacement peut être élidé).0 votes
@JonathanWakely - intéressant. Question ouverte : stackoverflow.com/questions/17481018/
4 votes
Pour être complet, ce que @JonathanWakely a dit a été traité dans un rapport de défaut et au moins les versions récentes de gcc et clang n'ont pas besoin du déplacement explicite là.
0 votes
Cette question est plus large que la cible dupliquée : par coïncidence, il s'agit essentiellement du même exemple, mais l'exemple n'est qu'une illustration ; il existe de nombreux autres cas non couverts par la cible dupliquée.