Quel est le meilleur moyen pour concaténer deux vecteurs?
Je suis en utilisant multitreading et souhaitez fusionner les résultats. Par exemple:
std::vector<int> A;
std::vector<int> B;
std::vector<int> AB;
Je veux AB avoir à la table des matières de l'Un et le contenu de B dans cet ordre. Quel est le moyen le plus efficace de faire quelque chose comme ça?
- Si la recherche de l'efficacité lorsque vous travaillez avec de grands contenants de taille, il peut être plus efficace d'utiliser la liste, où vous pouvez épissure de l'un à l'autre avec plusieurs opérations de pointeur. Mais la liste a de l'espace, les frais généraux (pensez à utiliser seule liste chaînée).
Vous devez vous connecter pour publier un commentaire.
insert
opérations ici.reserve
n'ont de mérite. Donc vous êtes tous les deux droit à un certain degré.std::move_iterator
(voir ici) qui est un itérateur adaptateur qui renvoie une référence rvalue quand déréférencement il. Qui permet (mais pas de garanties) que la source des éléments sont déplacés.C'est précisément ce que la fonction de membre de
std::vector::insert
est pourstd::vector::insert
est godawful lente lorsque vous essayez de faire est de concaténer deux vecteurs. C'est là que<algorithm>
est échouer et vous voulez vraimentstd::vector::extend
était une vraie méthode.insert
sur random-access itérateurs et réservés à l'avant.distance
a O(1) de la complexité). Encore, la garantie de la performance deinsert
sont quelque chose d'être conscient de quand vous pouvez souvent faire mieux en planifiant à l'avance.size < capacity
la plupart du temps, direction de la prévision sera probablement entraîner la non-réaffectation de la direction générale des instructions dans le pipeline d'instruction, la minimisation de la branche induite par la latence, sauf pour un faible nombre d'itérations. Cela suppose un bon vecteur de mise en œuvre, en plus de CPU instruction pipeline & [bon] direction de la prévision, mais ceux-ci sont assez fiables hypothèses pour une moderne suite d'outils et de machines de bureaux. Ne sais pas sur les smartphones mais..Dépend si vous en avez vraiment besoin de se concaténer les deux vecteurs ou vous voulez donner l'apparence de la concaténation de l'intérêt de l'itération. Le boost::rejoignez la fonction
http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/reference/utilities/join.html
vous donnera cette.
devrait vous donner
Note boost::joignez-vous à ne pas copier les deux vecteurs dans un nouveau conteneur
mais génère une paire d'itérateurs (gamme) qui couvrent la durée de
les deux récipients. Il y aura des conséquences sur les performances, mais peut-être
moins que la copie de toutes les données dans un nouveau conteneur d'abord.
Basé sur Cyrille V. Lyadvinsky répondre, j'ai fait une nouvelle version. Cet extrait de l'utilisation modèle et la surcharge. Avec elle, vous pouvez écrire
vector3 = vector1 + vector2
etvector4 += vector3
. J'espère que ça peut aider.::
est pris 😉v1 + v2
ne représente pas plus.@
comme en F#Dans la direction de Bradgonesurfing, en réponse, de nombreuses fois, on n'a pas vraiment besoin pour concaténer deux vecteurs (O(n)), mais plutôt juste travailler avec eux comme s'ils étaient enchaînés (O(1)). Si c'est votre cas, il peut être fait sans la nécessité de bibliothèques Boost.
L'astuce est de créer un vecteur de proxy: une classe wrapper qui manipule références de deux vecteurs de l'extérieur, vu comme une seule, contigus, qui peut ensuite être consulté/parcouru exactement comme vous le feriez sur un réel vecteur.
UTILISATION
Mise en ŒUVRE
PRINCIPAL AVANTAGE
Il est O(1) (constante de temps) pour la créer, et avec un minimum de supplément d'allocation de mémoire. Dans la pratique, c'est une opération rapide, même lorsque l'on considère les énormes vecteurs, puisque vous remplacez |B| (ou |A|+|B|) de l'élément de copies par zéro. Aussi, il offre exactement le comportement souhaité.
Vecteurs de concaténation est au moins O(|B|) (lorsque B est ajouté à Un), quelle que soit la technique employée. Dans votre cas, puisque vous avez l'intention de travailler avec une 3ème vecteur AB, il est O(|A|+|B|). En fonction des vecteurs de la taille et du nombre de concaténation des opérations nécessaires, cela peut être un goulot d'étranglement. L'astuce ci-dessus, il aborde.
CERTAINES CHOSES À CONSIDÉRER
l'accès de l'opérateur ([ ]). N'hésitez pas à inclure, mais gardez à l'esprit: puisque AB contient des références, de lui attribuer
les valeurs vont également affecter les éléments d'origine, à l'intérieur de A et/ou B. Si oui ou non ce est un
caractéristique souhaitable, c'est une application spécifique de la question que l'on doit
examiner attentivement.
le redimensionnement, etc.) aussi à "modifier" AB. Ce n'est pas nécessairement mauvais
(en fait, il peut être très pratique: AB n'a jamais besoin d'être explicitement
mis à jour pour tenir lui-même synchronisé à la fois à A et à B), mais il est
certainement un comportement, il faut être conscient.
< v1.taille()"), VecProxy temps d'accès, bien que constante, est également
plus lente que celle des vecteurs. Il peut donc ne pas être la voie à suivre si
vous devez, par exemple, à effectuer des millions de accès d'opérations par seconde,
c'est à dire si le goulot d'étranglement se situe dans les opérations d'accès.
il ne devrait pas être un gros problème.
ces procurations (puisqu'ils ne sont pas des vecteurs, après tout).
VecProxy, car pas tous les éléments appartiennent à la même conteneur.
Un plus simple variante qui n'était pas encore mentionné:
Et à l'aide d'algorithme de fusion:
Si vos vecteurs sont triés*, découvrez set_union de <algorithm>.
Il y a une plus approfondie exemple dans le lien
*grâce rlbond
Toutes les solutions sont correctes, mais je l'ai trouvé plus facile il suffit d'écrire une fonction pour mettre en œuvre cette. comme ceci:
De cette façon, vous pouvez éviter le placement temporaire comme ceci: