Efficacité de C ++ 11 push_back () avec std :: move versus emplace_back () pour les objects déjà construits

En C ++ 11, emplace_back() est généralement préféré (en termes d’efficacité) à push_back() car il permet la construction sur place, mais est-ce toujours le cas lorsque vous utilisez push_back(std::move()) avec un déjà object construit?

Par exemple, emplace_back() toujours préférable dans les cas suivants?

 std::ssortingng myssortingng("hello world"); std::vector myvector; myvector.emplace_back(myssortingng); myvector.push_back(std::move(myssortingng)); // (of course assuming we don't care about using the value of myssortingng after) 

En outre, y a-t-il un avantage dans l’exemple ci-dessus à faire plutôt:

 myvector.emplace_back(std::move(myssortingng)); 

ou le déménagement est-il entièrement redondant ou n’a-t-il aucun effet?

Voyons ce que font les différents appels que vous avez fournis:

  1. emplace_back(myssortingng) : Ceci est une construction sur place du nouvel élément avec n’importe quel argument que vous avez fourni. Puisque vous avez fourni une lvalue, cette construction sur place est en fait une construction de copie, c’est-à-dire que cela revient à appeler push_back(myssortingng)

  2. push_back(std::move(myssortingng)) : Cela appelle l’insertion de mouvement, qui dans le cas de std :: ssortingng est une construction de déplacement sur place.

  3. emplace_back(std::move(myssortingng)) : Ceci est encore une construction en place avec les arguments que vous avez fournis. Comme cet argument est une valeur, il appelle le constructeur de déplacement de std::ssortingng , c’est-à-dire qu’il s’agit d’une construction de déplacement sur place comme dans 2.

En d’autres termes, si elle est appelée avec un argument de type T, que ce soit une valeur ou une valeur, emplace_back et push_back sont équivalents.

Cependant, pour tout autre argument, emplace_back gagne la course, par exemple avec un caractère char const* dans un vector :

  1. emplace_back("foo") appelle ssortingng::ssortingng(char const*) pour la construction sur place.

  2. push_back("foo") doit d’abord appeler ssortingng::ssortingng(char const*) pour la conversion implicite nécessaire pour correspondre à la signature de la fonction, puis une insertion de déplacement comme dans le cas 2. ci-dessus. Par conséquent, il est équivalent à push_back(ssortingng("foo"))

Emplace_back obtient une liste de références rvalue et tente de construire un élément conteneur directement en place. Vous pouvez appeler emplace_back avec tous les types pris en charge par le constructeur de l’élément conteneur. Lorsque appel à emplace_back pour des parameters qui ne sont pas des références à rvalue, il revient à des références normales et au moins le constructeur de copie est appelé lorsque le paramètre et les éléments de conteneur sont du même type. Dans votre cas, ‘myvector.emplace_back (myssortingng)’ devrait faire une copie de la chaîne car le compilateur ne pourrait pas savoir que le paramètre myvector est mobile. Insérez donc le std :: move ce qui vous donne l’avantage désiré. Le push_back devrait fonctionner aussi bien que emplace_back pour les éléments déjà construits.