Quelle est la manière la moins chère d'initialiser un std::vector
partir d'un tableau de style C?
Exemple: dans la classe suivante, j'ai un vector
, mais en raison de restrictions extérieures, les données seront transmises sous forme de tableau de style C:
class Foo {
std::vector<double> w_;
public:
void set_data(double* w, int len){
// how to cheaply initialize the std::vector?
}
De toute évidence, je peux appeler w_.resize()
puis boucler sur les éléments, ou appeler std::copy()
. Existe-t-il de meilleures méthodes?
Réponses:
N'oubliez pas que vous pouvez traiter les pointeurs comme des itérateurs:
la source
assign
est certainement libre de les utiliser pour optimiser; au moins en VC ++, c'est exactement ce qu'il fait.v.end()
un itérateur pointant un après la fin avec un vecteur dans un cas similaire). Si vous obtenez une affirmation, alors quelque chose ne va pas ailleurs.Vous utilisez le mot initialiser pour que l'on ne sache pas s'il s'agit d'une affectation ponctuelle ou peut se produire plusieurs fois.
Si vous avez juste besoin d'une initialisation unique, vous pouvez la placer dans le constructeur et utiliser le constructeur de vecteur à deux itérateurs:
Sinon, utilisez assign comme suggéré précédemment:
la source
Vous pouvez `` apprendre '' automatiquement la taille du tableau:
J'espère que vous pouvez changer l'interface en set_data comme ci-dessus. Il accepte toujours un tableau de style C comme premier argument. Il arrive juste de le prendre par référence.
Comment ça fonctionne
[Mise à jour: voir ici pour une discussion plus complète sur l'apprentissage de la taille]
Voici une solution plus générale:
Cela fonctionne car le tableau est passé en tant que référence à un tableau. En C / C ++, vous ne pouvez pas passer un tableau en tant que fonction, au lieu de cela, il se désintégrera en un pointeur et vous perdrez la taille. Mais en C ++, vous pouvez passer une référence au tableau.
Passer un tableau par référence nécessite que les types correspondent exactement. La taille d'un tableau fait partie de son type. Cela signifie que nous pouvons utiliser le paramètre de modèle N pour connaître la taille pour nous.
Il pourrait être encore plus simple d'avoir cette fonction qui renvoie un vecteur. Avec les optimisations du compilateur appropriées en vigueur, cela devrait être plus rapide qu'il n'y paraît.
la source
return { begin(source_array), end(source_array) };
est également possibleEh bien, Pavel était proche, mais il existe même une solution plus simple et élégante pour initialiser un conteneur séquentiel à partir d'un tableau de style ac.
Dans ton cas:
la source
array
(ce qui signifie généralement que vous copiez à partir d'un tableau global ou local (déclaré dans la fonction actuelle)). Dans le cas de l'OP, il reçoit un pointeur et une longueur, et comme ce n'est pas basé sur la longueur, ils ne peuvent pas changer pour recevoir un pointeur vers un tableau de taille ou quoi que ce soit, doncstd::end
ne fonctionnera pas.vector
ne surcharge pasoperator()
, donc cela ne compile pas.std::end
être appelé sur un pointeur ne sert à rien non plus (la question demande d'attribuer un vecteur à partir d'un pointeur et d'une variable de longueur séparée). Cela améliorerait votre réponse pour montrer plus de contexte sur ce que vous essayez de suggérerLa réponse générique rapide:
ou question spécifique:
basé sur ci - dessus : n'oubliez pas que vous pouvez traiter les pointeurs comme des itérateurs
la source
std::vector<double>::assign
c'est la voie à suivre, car c'est peu de code . Mais comment ça marche, en fait? N'est-il pas redimensionné puis copié? Dans l'implémentation MS de STL, je l'utilise exactement.J'ai peur qu'il n'y ait pas de moyen plus rapide d'implémenter (ré) initialiser votre
std::vector
.la source