Existe-t-il un moyen standard de déplacer une plage dans un vecteur?

Considérons le programme suivant qui insère une série d’éléments dans un vecteur:

vector v1; vector v2; v1.push_back("one"); v1.push_back("two"); v1.push_back("three"); v2.push_back("four"); v2.push_back("five"); v2.push_back("six"); v1.insert(v1.end(), v2.begin(), v2.end()); 

Cela copie efficacement la plage, en allouant suffisamment d’espace dans le vecteur cible pour l’ensemble de la plage afin qu’un maximum d’un redimensionnement soit requirejs. Considérons maintenant le programme suivant qui tente de déplacer une plage dans un vecteur:

 vector v1; vector v2; v1.push_back("one"); v1.push_back("two"); v1.push_back("three"); v2.push_back("four"); v2.push_back("five"); v2.push_back("six"); for_each ( v2.begin(), v2.end(), [&v1]( ssortingng & s ) { v1.emplace_back(std::move(s)); }); 

Cela effectue un déplacement réussi mais ne bénéficie pas des avantages de l’insertion () de l’espace de préallocation dans le vecteur cible, ce qui permet de redimensionner le vecteur plusieurs fois pendant l’opération.

Donc, ma question est la suivante: existe-t-il un équivalent en encart qui peut déplacer une plage dans un vecteur?

Vous utilisez un move_iterator avec insert :

 v1.insert(v1.end(), make_move_iterator(v2.begin()), make_move_iterator(v2.end())); 

L’exemple du 24.5.3 est presque exactement celui-ci.

Vous obtiendrez l’optimisation que vous souhaitez si (a) vector::insert utilise la dissortingbution iterator-tag pour détecter l’iterator à access aléatoire et pré-calculer la taille (que vous avez supposée faire dans votre exemple qui copie), et (b ) move_iterator conserve la catégorie d’iterator de l’iterator qu’il encapsule (ce qui est requirejs par la norme).

Sur un point obscur: je suis presque sûr que vector::insert peut être mis en place à partir de la source (ce qui n’est pas pertinent ici, car la source est du même type que la destination, donc un emplace est identique à un copier / déplacer, mais serait pertinent pour des exemples autrement identiques). Je n’ai pas encore trouvé d’énoncé indiquant qu’il est nécessaire de le faire, je viens de le déduire du fait que l’exigence sur la paire d’iterators i,j passée à l’ insert est que T soit EmplaceConstructible de *i .

  1. algorithme std::move avec préallocation:

     #include  #include  v1.reserve(v1.size() + v2.size()); // optional std::move(v2.begin(), v2.end(), std::back_inserter(v1)); 
  2. Ce qui suit serait plus souple encore:

     v1.insert(v1.end(), std::make_move_iterator(v2.begin()), std::make_move_iterator(v2.end())); 

    Steve Jessop a fourni des informations de base sur ce que fait exactement et probablement comment cela se passe.