111 votes

Comment copier le contenu d'un tableau dans un std :: vector en C ++ sans effectuer de boucle?

J'ai un tableau de valeurs qui est transmis à ma fonction à partir d'une partie différente du programme que je dois stocker pour un traitement ultérieur. Comme je ne sais pas combien de fois ma fonction sera appelée avant le moment de traiter les données, j'ai besoin d'une structure de stockage dynamique, j'ai donc choisi un std :: vector. Je ne veux pas avoir à faire la boucle standard pour push_back toutes les valeurs individuellement, ce serait bien si je pouvais tout copier en utilisant quelque chose de similaire à memcpy.

203voto

MattyT Points 3195

Il y a eu beaucoup de réponses ici, et à peu près tous d'entre eux vont faire le travail.

Cependant, il ya quelques conseils trompeurs!

Voici les options:

vector<int> dataVec;

int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
unsigned dataArraySize = sizeof(dataArray) / sizeof(int);

// Method 1: Copy the array to the vector using back_inserter.
{
    copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}

// Method 2: Same as 1 but pre-extend the vector by the size of the array using reserve
{
    dataVec.reserve(dataVec.size() + dataArraySize);
    copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}

// Method 3: Memcpy
{
    dataVec.resize(dataVec.size() + dataArraySize);
    memcpy(&dataVec[dataVec.size() - dataArraySize], &dataArray[0], dataArraySize * sizeof(int));
}

// Method 4: vector::insert
{
    dataVec.insert(dataVec.end(), &dataArray[0], &dataArray[dataArraySize]);
}

// Method 5: vector + vector
{
    vector<int> dataVec2(&dataArray[0], &dataArray[dataArraySize]);
    dataVec.insert(dataVec.end(), dataVec2.begin(), dataVec2.end());
}

Pour couper une longue histoire courte de la Méthode 4, à l'aide de vecteur::insert, est le meilleur pour bsruth du scénario.

Voici quelques détails techniques:

La méthode 1 est probablement le plus facile à comprendre. Il suffit de copier chaque élément de la matrice et la pousser dans le dos du vecteur. Hélas, c'est lent. Parce qu'il y a une boucle (implicite avec la fonction de copie), chaque élément doit être traitée individuellement; aucune des améliorations de performances peut être faite sur la base du fait que nous savons que le tableau et les vecteurs sont des blocs contigus.

Méthode 2 est une suggestion d'amélioration de la performance de la Méthode 1; pré-réserver la taille du tableau avant de l'ajouter. Pour les grandes matrices cela pourrait aider. Cependant, le meilleur conseil est de ne jamais utiliser de la réserve, à moins que le profilage suggère que vous pouvez être en mesure d'obtenir une amélioration (ou vous devez vous assurer que votre itérateurs ne vont pas être invalidé). Bjarne accepte. D'ailleurs, j'ai trouvé que cette méthode a effectué la plus lente, la plupart du temps si je suis en difficulté globale pour expliquer pourquoi il a été régulièrement considérablement plus lente que la méthode 1...

La méthode 3 est l'ancienne école de la solution de jeter un peu de C, dans le le problème! Fonctionne très bien et rapide pour POD types. Dans ce cas de redimensionnement est nécessaire pour être appelé depuis memcpy œuvres à l'extérieur des limites de vecteur et il n'y a aucun moyen de dire un vecteur que sa taille a changé. En plus d'être un vilain solution (octet de la copie!) rappelez-vous que cela peut être utilisé uniquement pour les POD types. Je n'aurais jamais utiliser cette solution.

Méthode 4 est la meilleure façon d'aller. C'est le sens est clair, c'est (généralement) de la manière la plus rapide et cela fonctionne pour tous les objets. Il n'y a pas d'inconvénient à l'utilisation de cette méthode pour cette application.

Méthode 5 est un tweak sur la Méthode 4 - copier le tableau dans un vecteur, puis les ajouter. Bonne option généralement rapide-ish et clair.

Enfin, vous êtes conscient que vous pouvez utiliser des vecteurs en place de tableaux, droite? Même lorsqu'une fonction attend de style c des tableaux, vous pouvez utiliser des vecteurs:

vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");

Espère que ça aide quelqu'un là-bas!

108voto

Drew Hall Points 15917

Si vous pouvez construire le vecteur après que vous ayez obtenu le tableau & taille de la matrice, vous pouvez simplement dire:

std::vector<ValueType> vec(a, a + n);

...en supposant que a est la matrice de & n est le nombre d'éléments qu'il contient. Sinon, std::copy() w/resize() fera l'affaire.

Je voudrais rester à l'écart de memcpy (), sauf si vous pouvez être sûr que les valeurs sont plaine-des données anciennes (POD) types.

Aussi, intéressant de noter qu'aucun de ces évite vraiment de la boucle for, c'est juste une question de savoir si vous devez le voir dans votre code ou pas. O(n) les performances d'exécution est inévitable pour copier les valeurs.

Enfin, notez qu'en C les tableaux sont parfaitement valables conteneurs pour la plupart des algorithmes de la STL--le pointeur brut est équivalent à begin(), et (ptr + n) est équivalent à la fin().

35voto

Torlack Points 2910

Si vous ne faites que remplacer les données existantes, vous pouvez le faire.

 std::vector<int> data; // evil global :)

void CopyData(int *newData, size_t count)
{
   data.assign(newData, newData + count);
}
 

11voto

luke Points 16255

std :: copy est ce que vous cherchez.

8voto

bsruth Points 1603

Depuis je ne peux éditer mon propre réponse, je vais faire un composite de réponse de l'autre des réponses à ma question. Merci à tous ceux qui ont répondu.

En utilisant std::copy, c'est encore itère dans le fond, mais vous n'avez pas à taper le code.

int foo(int* data, int size)
{
   static std::vector<int> my_data; //normally a class variable
   std::copy(data, data + size, std::back_inserter(my_data));
   return 0;
}

L'utilisation de memcpy. C'est probablement mieux utilisé pour les types de données de base (c'est à dire de type int), mais pas pour les plus complexes des tableaux de structures ou classes.

vector<int> x(size);
memcpy(&x[0], source, size*sizeof(int));

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:

X