la façon la plus rapide pour convertir un std::vector pour un autre std::vector
Quel est le moyen le plus rapide (si il y a un autre) pour convertir un std::vector d'un type à l'autre (avec l'idée de gagner de la place)? Par exemple:
std::vector<unsigned short> ----> std::vector<bool>
de toute évidence, nous supposons que le premier vecteur ne contient que des 0 et des 1. La copie de l'élément par élément est très inefficace dans le cas d'un très grand vecteur.
Question conditionnelle:
Si vous pensez qu'il n'y a aucun moyen de le faire plus rapidement, est-il un complexe de type de données qui permet la conversion rapide d'un type de données à un autre?
L'OP veut économiser de la mémoire.
R. Martinho Fernandes: Vous l'avez!!! Je veux de la magie, unfortainatly std::do_magic() ne semble pas exister.
std::vector<bool>
est spécialisé pour être efficace en terme de mémoire.R. Martinho Fernandes: Vous l'avez!!! Je veux de la magie, unfortainatly std::do_magic() ne semble pas exister.
vector<bool>
est une catastrophe. Même STL auteurs admettre que c'était une erreur.OriginalL'auteur inf.ig.sh | 2011-10-26
Vous devez vous connecter pour publier un commentaire.
Arrêter.
Un
std::vector<bool>
est... non.std::vector
a une spécialisation pour l'utilisation du type debool
, ce qui entraîne certains changements dans lavector
. À savoir, il cesse de se comporter comme unstd::vector
.Il y a certaines choses que le niveau de garanties que vous pouvez faire avec un
std::vector
. Etvector<bool>
viole de ces garanties. Donc, vous devriez être très prudent quant à leur utilisation.De toute façon, je vais faire semblant que vous avez dit
vector<int>
au lieu devector<bool>
, comme le dernier complique vraiment les choses.Que si vous le faites mal.
Vecteur de la coulée du type que vous voulez doit être fait avec soin pour être efficace.
Si la source
T
est de type cabriolet à la destinationT
, alors c'est fonctionne très bien:Décent implémentations devraient reconnaître quand ils ont eu accès aléatoire itérateurs et d'optimiser l'allocation de la mémoire et de la boucle de manière appropriée.
Le plus gros problème pour les non-convertibles types que vous aurez pour les types simples est de ne pas faire cela:
Que c'est mal. Qui va allouer un tampon de la bonne taille, mais il aussi le remplir avec des données. À savoir, par défaut construit
int
s (int()
).Au lieu de cela, vous devriez faire ceci:
Cette réserve de capacité égale à l'original de vecteur de, mais aussi d'assurer qu'aucun défaut de construction. Vous pouvez maintenant
push_back
à votre contenu de coeurs, sachant que vous ne sera jamais la cause de réaffectation dans votre nouveau vecteur.À partir de là, vous pouvez simplement faire une boucle sur chaque entrée dans la vieille vecteur, de faire la conversion, en tant que de besoin.
char
que le type sous-jacent plutôt queint
(depuisint
sera à moins aussi large queshort
). Mais en supposant que c'est juste un exemple montrant comment copier de manière efficace, la réponse est très bon.Votre answear ist à peu près exactement ce que je cherchais. Merci.
Quel a été le -1 pour?
-1 pour avertir les
vector<bool>
au lieu de vous suggérer la meilleure et la plus évidente de la solution, qui est le constructeur qui prend deux itérateurs. Kibitzing sur les détails de l'exemple appartient dans les commentaires ou à la fin de la réponse, et non comme un remplacement pour la meilleure solution...Votre suggestion nécessite non seulement ignorer les dangers inhérents à l'utilisation de
vector<bool>
, mais nécessite également une conversion implicite entre les types en question. Qui, dans cet exemple peut être unbool
, mais l'OP certainement semblait le suggérer est allé delà de cet exemple. L'écriture d'une conversion implicite n'est pas quelque chose à faire pour chaque type.OriginalL'auteur Nicol Bolas
Il n'y a aucun moyen d'éviter la copie, depuis un
std::vector<T>
est distinctetype de
std::vector<U>
, et il n'y a aucun moyen pour eux de partager lesde la mémoire. Autre que cela, il dépend de la façon dont les données sont mappées. Si l'
cartographie correspond à une conversion implicite (par exemple,
unsigned short
àbool
), puis il suffit de créer un nouveau vecteur à l'aide de la fin et de début deles itérateurs de la vieille va faire l'affaire:
Si la cartographie n'est pas seulement une conversion implicite (et cela inclut
les cas où vous souhaitez vérifier les choses; par exemple, que le
unsigned short
ne contenir que
0
ou1
), ensuite cela devient plus compliqué. L'la solution la plus évidente serait d'utiliser std::transform:
où
TranformationObject
est un objet fonctionnel qui ne l'transformation, par exemple:
(Notez que je suis juste en utilisant cette fonction de transformation comme un exemple.
Si la seule chose qui distingue la transformation de la fonction de
une conversion implicite est de la vérification, il peut être plus rapide pour vérifier
toutes les valeurs de
oldV
d'abord, à l'aide destd::for_each
, et ensuite utiliserles deux itérateur constructeur ci-dessus).
Selon le coût de défaut de construire le type de cible, il peut être
plus rapide pour créer le nouveau vecteur avec la bonne taille, puis écraser
c':
Enfin, une autre possibilité serait d'utiliser un
boost::transform_iterator
. Quelque chose comme:À de nombreux égards, c'est la solution que je préfère, selon la façon dont
boost::transform_iterator
a été mis en œuvre, il pourrait également être lela plus rapide.
OriginalL'auteur James Kanze
Vous devriez être en mesure d'utiliser
assign
comme ceci:std::vector<bool> u(b.begin(), v.end());
.qui devrait être
u(v.begin(), v.end());
je pense?Oui, il y a une faute de frappe. Le commentaire est trop vieux pour être édité. Merci pour le spotting.
OriginalL'auteur Vlad
Le moyen le plus rapide de le faire est de pas le faire. Par exemple, si vous savez à l'avance que vos articles seulement besoin d'un octet pour le stockage, l'utilisation d'un taille en octets de vecteur pour commencer. Vous trouverez qu'il est difficile de trouver un moyen plus rapide que ça 🙂
Si ce n'est pas possible, alors il suffit d'absorber le coût de la conversion. Même si c'est un peu lent (et c'est pas sûr, voir Nicol est une excellente réponse pour plus de détails), il est toujours nécessaire. Si ce n'était pas le cas, vous serait tout simplement le laisser dans le plus grand type de vecteur.
OriginalL'auteur paxdiablo
OriginalL'auteur Vikash Kumar Sriwastava
Tout d'abord, un avertissement: "ne faites pas ce que je suis sur le point de suggérer. C'est dangereux et ne doit jamais être fait. Cela dit, si vous venez de prendre un tout petit peu plus les performances de N'Importe Quoi...
Tout d'abord, il y a quelques mises en garde. Si vous ne respectez pas les présentes, vous ne pouvez pas faire ceci:
Le vecteur doit contenir plaine-vieux-données. Si votre type a des pointeurs, ou utilise un destructeur, ou a besoin d'un opérateur = pour copier correctement ... ne le faites pas.
Le sizeof() à la fois vecteur de contenus types doivent être les mêmes. C'est, vector< A > pouvez copier vector< B > que si sizeof(A) == sizeof(B).
Ici est assez stable méthode:
Ce qui fait un très rapide, bloc copie de la mémoire contenue dans le vecteur b, directement brisant toutes les données que vous avez dans un vecteur. Il n'a pas d'appel des constructeurs, il ne fait pas de vérification de la sécurité, et c'est beaucoup plus rapide que les autres méthodes présentées ici. Un compilateur optimisant devrait être en mesure de correspondre à la vitesse de la ce en théorie, mais sauf si vous êtes en utilisant une exceptionnellement bonne, il ne va pas (j'ai vérifié avec Visual C++ il y a quelques années, et il n'était même pas proche).
Aussi, compte tenu de ces contraintes, vous pourriez force (via void *) dispose que d'un seul type de vecteur à l'autre et l'échange -- j'ai eu un exemple de code pour cela, mais il a commencé à suinter de l'ectoplasme sur mon écran, donc je l'ai supprimé.
OriginalL'auteur AHelps
La copie de l'élément par élément n'est pas très inefficace. std::vector fournit à constante de temps d'accès à l'un quelconque de ses éléments, d'où l'opération sera O(n) dans l'ensemble. Vous ne le remarqueront pas.
OriginalL'auteur Daniel Daranas
OriginalL'auteur Jerry Miller