Quelle est la manière la plus simple de convertir un tableau en vecteur?

92

Quelle est la manière la plus simple de convertir un tableau en vecteur?

void test(vector<int> _array)
{
  ...
}

int x[3]={1, 2, 3};
test(x); // Syntax error.

Je veux convertir x du tableau int en vecteur de la manière la plus simple.

Amir Saniyan
la source

Réponses:

138

Utilisez le vectorconstructeur qui prend deux itérateurs, notez que les pointeurs sont des itérateurs valides et utilisez la conversion implicite de tableaux en pointeurs:

int x[3] = {1, 2, 3};
std::vector<int> v(x, x + sizeof x / sizeof x[0]);
test(v);

ou

test(std::vector<int>(x, x + sizeof x / sizeof x[0]));

sizeof x / sizeof x[0]est évidemment 3dans ce contexte; c'est la manière générique d'obtenir le nombre d'éléments dans un tableau. Notez que x + sizeof x / sizeof x[0]pointe un élément au - delà du dernier élément.

Fred Foo
la source
1
Pouvez-vous l'expliquer s'il vous plaît? J'ai déjà lu cela vector<int> a(5,10);signifie make room for 5 int` et je les initialise avec 10. Mais comment fonctionne votre x, x + ...? peux-tu expliquer?
Asif Mushtaq
1
@UnKnown plutôt que de sélectionner vector<int>::vector(size_type, int), il sélectionne vector<int>::vector(int*, int*), qui copie la plage indiquée par cette paire de pointeurs. Le premier est la surcharge (2), le second est la surcharge (4) ici
Caleth
1
Sur c ++ 11, std :: extend est meilleur que la méthode sizeof. sizeof x / sizeof x[0] == std::extent<decltype(x)>::value
Isaac Pascual
113

Personnellement, j'aime assez l'approche C ++ 2011 car elle ne vous oblige ni à utiliser sizeof()ni à vous souvenir d'ajuster les limites du tableau si jamais vous changez les limites du tableau (et vous pouvez définir la fonction appropriée dans C ++ 2003 si vous le souhaitez, aussi ):

#include <iterator>
#include <vector>
int x[] = { 1, 2, 3, 4, 5 };
std::vector<int> v(std::begin(x), std::end(x));

De toute évidence, avec C ++ 2011, vous souhaiterez peut-être utiliser les listes d'initialiseurs de toute façon:

std::vector<int> v({ 1, 2, 3, 4, 5 });
Dietmar Kühl
la source
2
copie-t-il le tableau ou il pointe simplement vers lui? je suis préoccupé par la performance
kirill_igum
2
std::vector<T>possède toujours les Tobjets. Cela a deux implications: lors de l'insertion d'objets dans un vecteur, ils sont copiés et ils sont colocalisés en mémoire. Pour des objets raisonnablement petits, par exemple des séquences de chaînes courtes, la colocalisation est un gain de performance majeur. Si vos objets sont volumineux et coûteux à copier, vous souhaiterez peut-être stocker des pointeurs [gérés en quelque sorte par les ressources] vers les objets. L'approche la plus efficace dépend des objets mais vous avez le choix.
Dietmar Kühl
Donc, si je veux interfacer des bibliothèques c ++ et ac et copier du c-array au vecteur et inversement, il n'y a aucun moyen de payer la pénalité de 2 copies? (J'utilise la bibliothèque propre et gsl)
kirill_igum
16

Les pointeurs peuvent être utilisés comme n'importe quel autre itérateur:

int x[3] = {1, 2, 3};
std::vector<int> v(x, x + 3);
test(v)
Rafał Rawicki
la source
2
Dans la vraie vie, vous voudrez peut-être extraire la taille du tableau, par exemple en utilisant const size_t X_SIZE = 3;pour indiquer la taille du tableau ou en le calculant à partir de sizeof. J'ai omis cette partie pour des raisons de lisibilité.
Rafał Rawicki
11

Vous posez la mauvaise question ici - au lieu de tout forcer dans un vecteur, demandez comment vous pouvez convertir le test pour qu'il fonctionne avec des itérateurs au lieu d'un conteneur spécifique. Vous pouvez également fournir une surcharge afin de conserver la compatibilité (et gérer d'autres conteneurs en même temps gratuitement):

void test(const std::vector<int>& in) {
  // Iterate over vector and do whatever
}

devient:

template <typename Iterator>
void test(Iterator begin, const Iterator end) {
    // Iterate over range and do whatever
}

template <typename Container>
void test(const Container& in) {
    test(std::begin(in), std::end(in));
}

Ce qui vous permet de faire:

int x[3]={1, 2, 3};
test(x); // Now correct

( Démo Ideone )

Flexo
la source
"au lieu de tout forcer dans un vecteur, demandez comment vous pouvez convertir le test pour qu'il fonctionne avec des itérateurs au lieu d'un conteneur spécifique." Pourquoi est-ce mieux?
Aquirdturtle
1
@aquirdturtle parce que maintenant, au lieu de ne prendre en charge que les vecteurs, vous prenez en charge les listes et les tableaux, vous augmentez les conteneurs et transformez les itérateurs et les plages et ....
Flexo
2
et vous n'avez pas besoin de copier les données
Courses de légèreté en orbite le
2

Un moyen simple peut être d'utiliser une assign()fonction prédéfinie dans la vectorclasse.

par exemple

array[5]={1,2,3,4,5};

vector<int> v;
v.assign(array, array+5); // 5 is size of array.
3251_ali
la source
2
Équivaut à l'utilisation du ctor, qui a été mentionné dans les réponses existantes il y a sept ans environ. N'ajoute rien ...
Courses de légèreté en orbite