505 votes

push_back vs emplace_back

Je suis un peu confus en ce qui concerne la différence entre push_back et emplace_back.

void emplace_back(Type&& _Val);
void push_back(const Type& _Val);
void push_back(Type&& _Val);

Comme il y a un push_back surcharge de prendre une référence rvalue je n'arrive pas à voir quel est le but de emplace_back devient?

411voto

Thomas Petit Points 4100

En plus de ce visiteur dit :

La fonction void emplace_back(Type&& _Val) fournis par MSCV10 est non conforme et redondantes, car comme vous l'avez remarqué il est strictement équivalent à push_back(Type&& _Val).

Mais le vrai C++0x forme d' emplace_back , c'est vraiment utile: void emplace_back(Args&&...);

Au lieu de prendre un value_type il faut un variadic liste d'arguments, ce qui signifie que vous pouvez maintenant parfaitement en avant l'argument et de construire directement un objet dans un contenant sans que temporaire.

C'est utile, Parce que peu importe combien l'intelligence RVO et déplacer sémantique apporter à la table, il y a encore compliqué les cas où un push_back est susceptible de rendre inutiles les copies (ou déplacer). Par exemple, avec les traditionnels insert() fonction d'un std::map, vous devez créer un temporaire, qui sera ensuite copié dans un std::pair<Key, Value>, qui seront alors copiés dans la carte :

std::map<int, Complicated> m;
int anInt = 4;
double aDouble = 5.0;
std::string aString = "C++";

// cross your finger so that the optimizer is really good
m.insert(std::make_pair(4, Complicated(anInt, aDouble, aString))); 

// should be easier for the optimizer
m.emplace(4, anInt, aDouble, aString);

Alors pourquoi n'ont-ils pas mettre en œuvre la bonne version de emplace_back dans MSVC ? En fait, il m'énerve trop il y a longtemps, j'ai donc posé la même question sur le Visual C++ blog. Voici la réponse de Stephan T Lavavej, le mainteneur officiel de l'Visual C++ de la bibliothèque standard de mise en œuvre de Microsoft.

Q : la bêta 2 emplace fonctions juste une sorte d'espace réservé à l'instant ?

R : Comme vous le savez peut-être, variadic templates ne sont pas mises en œuvre dans VC10. Nous simuler avec préprocesseur machines pour des choses comme make_shared<T>(), tuple, et le nouveau les choses en <functional>. Cette préprocesseur machines est relativement difficile à utiliser et à entretenir. Aussi, il affecte de manière significative la compilation la vitesse, comme nous l'avons à plusieurs reprises inclure subheaders. En raison d'un la combinaison de nos contraintes de temps et la vitesse de compilation préoccupations, nous n'ai pas simulé variadic templates dans notre emplace fonctions.

Lorsque les variadic templates sont mis en œuvre dans le compilateur, vous pouvez s'attendre à ce que nous allons profiter de dans les bibliothèques, y compris dans notre emplace fonctions. Nous prenons la conformité très au sérieux, mais malheureusement, nous ne pouvons pas tout faire tout à la fois.

C'est une décision compréhensible. Tout le monde qui a essayé juste une fois pour émuler variadic template avec préprocesseur horribles trucs savoir comment dégueulasse ce genre de choses arrive.

151voto

visitor Points 4066

emplace_back ne devriez pas prendre un argument de type vector::value_type, mais au lieu variadic arguments qui sont transmis au constructeur de l'élément ajouté.

template <class... Args> void emplace_back(Args&&... args); 

Il est possible de passer un value_type , qui sera transmis au constructeur de copie.

Car il transmet les arguments, cela signifie que si vous n'avez pas rvalue, cela signifie que le conteneur va stocker un "copié" copie, pas un déplacé de la copie.

 std::vector<std::string> vec;
 vec.emplace_back(std::string("Hello")); // moves
 std::string s;
 vec.emplace_back(s); //copies

Mais la ci-dessus doivent être identiques à ce qui push_back . C'est probablement plutôt pour les cas d'utilisation comme:

 std::vector<std::pair<std::string, std::string> > vec;
 vec.emplace_back(std::string("Hello"), std::string("world")); 
 // should end up invoking this constructor:
 //template<class U, class V> pair(U&& x, V&& y);
 //without making any copies of the strings

7voto

Germán Diago Points 1396

emplace_back conforme de la mise en œuvre va de l'avant des arguments au vector<Object>::value_typeconstructeur lorsqu'il est ajouté au vecteur. Je me souviens de Visual Studio ne prend pas en charge variadic templates, mais variadic templates seront pris en charge dans Visual Studio 2013 RC, donc je suppose que conforme signature sera ajoutée.

Avec emplace_back, si vous en avant les arguments directement à l' vector<Object>::value_type constructeur, vous n'avez pas besoin d'un type de meubles ou copiable pour emplace_back fonction à proprement parler. Dans l' vector<NonCopyableNonMovableObject> des cas, ce n'est pas utile, puisqu' vector<Object>::value_type besoin d'un copiable ou movable type de croître.

Mais notez que cela pourrait être utile pour std::map<Key, NonCopyableNonMovableObject>, car une fois que vous allouer une entrée dans la carte, il n'a pas besoin d'être déplacé ou copié jamais plus, contrairement à d' vector, ce qui signifie que vous pouvez utiliser std::map efficacement avec un mappage de type qui n'est ni copiable, ni meubles.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by: