Comment convertir un vecteur en tableau

352

Comment convertir un std::vector<double>en un double array[]?

ganuke
la source
9
Un peu la question de savoir pourquoi? Vous pouvez accéder à un vecteur sous forme de tableau. Que fait un tableau qu'un vecteur ne fait pas?
Michael Dorgan
96
@Michael Le cas d'utilisation typique que j'ai utilise un vecteur dans mon propre code et a besoin d'appeler une fonction tierce qui prend un tableau
Michael Mrozek
7
La terminologie utilisée est source de confusion. Un pointeur n'est pas un tableau. Voulons-nous un pointeur vers le premier élément d'un tableau ou un tableau?
GManNickG
7
absolument une vraie question - assez simple et facile à interpréter aussi. veuillez rouvrir.
dbliss
10
"Je me demande un peu pourquoi?" - Tout d'abord, l'abus de cette phrase. Deuxièmement, il saigne clairement pourquoi.
Jim Balter

Réponses:

533

Il y a une astuce assez simple à faire, car la spécification garantit maintenant que les vecteurs stockent leurs éléments de manière contiguë:

std::vector<double> v;
double* a = &v[0];
Michael Mrozek
la source
29
@ganuke Vous ne copiez pas, vous créez un pointeur qui pointe vers le tableau réel que le vecteur utilise en interne. Si vous voulez copier la réponse de GMan explique comment
Michael Mrozek
4
@ganuke: Qu'est-ce que "le tableau"? Vous devez fournir plus d'informations. Quelle est la grande image?
GManNickG
6
@ganuke Non, vous avez juste besoin d'un double*qui pointe vers les mêmes données. Cette réponse fonctionne exactement pour ce cas
Michael Mrozek
6
@guneykayim Le vecteur possède cette mémoire, vous ne devriez pas la libérer
Michael Mrozek
23
std::vector<double> v; double* a = v.data();
sinoTrinity
148

Pourquoi? Vous devez clarifier: avez-vous besoin d'un pointeur sur le premier élément d'un tableau ou d'un tableau?

Si vous appelez une fonction API qui attend la première, vous pouvez le faire do_something(&v[0], v.size()), où vest un vecteur de doubles. Les éléments d'un vecteur sont contigus.

Sinon, il vous suffit de copier chaque élément:

double arr[100];
std::copy(v.begin(), v.end(), arr);

Assurez-vous non seulement qu'il arrest assez grand, mais qu'il arrest rempli, ou que vous avez des valeurs non initialisées.

GManNickG
la source
15
Remarque: utilisez v.size () pour obtenir le nombre d'éléments pour le nouveau tableau: double arr [v.size ()];
rbaleksandar
7
@rbaleksandar: Les tableaux ne peuvent pas avoir une taille d'expression non constante.
GManNickG
@GManNickG: Cela fonctionne, mais je pense qu'il y a un malentendu ici. Imaginez ce qui suit: vous avez une classe avec un tas de pointeurs de différents types qui doivent pointer vers des tableaux, qui ne sont pas connus au moment où vous définissez votre classe et qui sont ensuite créés en vidant divers vecteurs et en utilisant leur paramètre de taille pour déterminer la quantité d'espace à utiliser. Un autre exemple: une fonction simple void arrayTest (unsigned int arrSize), qui crée un tableau (short arr [arrSize];) en utilisant son paramètre de fonction pour la taille.
rbaleksandar
1
@rbaleksandar Pas de malentendu; en C ++ 11 et versions antérieures, les tailles de tableau doivent être des expressions constantes intégrales. Votre exemple de fonction est une utilisation courante des VLA en C, mais uniquement pris en charge par l'extension (non standard) en C ++. Cependant, il peut arriver en C ++ 14: stackoverflow.com/a/17318040/87234 . Mais pour l'instant, ce n'est tout simplement pas une option standard.
GManNickG
1
@GManNickG Je pense que @Jet dit que si vous voulez convertir un vecteur en tableau, et que vous avez l'intention de dimensionner le tableau en utilisant la size()fonction du, std:vectorvous devrez utiliser newou mallocfaire cela. Comme cela a déjà été souligné (par vous), ce double arr[v.size()]n'est pas valable. Utiliser un vecteur à la place de nouveau est une bonne idée, mais le point essentiel de la question est de savoir comment convertir un vecteur en tableau.
RyanP
17
vector<double> thevector;
//...
double *thearray = &thevector[0];

Il est garanti que cela fonctionne selon la norme, mais il y a quelques mises en garde: en particulier, veillez à n'utiliser thearrayque pendant qu'il thevectorest dans le champ d'application.

user168715
la source
4
... et assurez-vous que le vecteur ne l'est pas empty(), sinon cela invoquerait l'UB redouté.
sbi
13

Les vecteurs sont efficacement des réseaux sous la peau. Si vous avez une fonction:

void f( double a[]);

vous pouvez l'appeler comme ceci:

vector <double> v;
v.push_back( 1.23 )
f( &v[0] );

Vous ne devriez jamais avoir besoin de convertir un vecteur en une véritable instance de tableau.


la source
1
Je pense que vous vouliez dire f( &v[0] );pour votre dernière ligne
Michael Mrozek
10

Quant à std::vector<int> vecvec pour obtenir int*, vous pouvez utiliser deux méthodes:

  1. int * arr = & vec [0];

  2. int * arr = vec.data ();

Si vous souhaitez convertir n'importe quel type de Tvecteur en T* array, remplacez simplement ce qui précède intparT .

Je vais vous montrer pourquoi les deux ci-dessus fonctionnent, pour une bonne compréhension?

std::vector est un tableau dynamique essentiellement.

Membre des données principales comme ci-dessous:

template <class T, class Alloc = allocator<T>>
class vector{
    public:
        typedef T          value_type;
        typedef T*         iterator;
        typedef T*         pointer;
        //.......
    private:
        pointer start_;
        pointer finish_;
        pointer end_of_storage_;

    public:
        vector():start_(0), finish_(0), end_of_storage_(0){}
    //......
}

le range (start_, end_of_storage_) est toute la mémoire du tableau allouée par le vecteur;

le range(start_, finish_) est toute la mémoire matricielle du vecteur utilisé;

le range(finish_, end_of_storage_) est la mémoire de tableau de sauvegarde.

Par exemple, comme pour un vecteur vec. qui a {9, 9, 1, 2, 3, 4} est le pointeur peut aimer le ci-dessous.

entrez la description de l'image ici

So &vec[0]= start_ (address.) (Start_ est équivalent à int * array head)

Dans c++11 la data()fonction membre, renvoyez simplement start_

pointer data()
{ 
     return start_; //(equivalent to `value_type*`, array head)
}
Jayhello
la source
2

Nous pouvons le faire en utilisant la méthode data (). C ++ 11 fournit cette méthode.

Extrait de code

#include<bits/stdc++.h>
using namespace std;


int main()
{
  ios::sync_with_stdio(false);

  vector<int>v = {7, 8, 9, 10, 11};
  int *arr = v.data();

  for(int i=0; i<v.size(); i++)
  {
    cout<<arr[i]<<" ";
  }

  return 0;
}
rashedcs
la source
2
std::vector<double> vec;
double* arr = vec.data();
Toby
la source
1

Si vous avez une fonction, alors vous avez probablement ceci: foo(&array[0], array.size());. Si vous avez réussi à vous retrouver dans une situation où vous avez besoin d'un tableau, vous devez refactoriser, les vecteurs sont essentiellement des tableaux étendus, vous devez toujours les utiliser.


la source
-1

Vous pouvez faire quelque chose comme ça

vector <int> id;
vector <double> v;

if(id.size() > 0)
{
    for(int i = 0; i < id.size(); i++)
    {
        for(int j = 0; j < id.size(); j++)
        {
            double x = v[i][j];
            cout << x << endl;
        }
    }
}
Sakthi Vignesh
la source
v [i] [j]; pour 2d array
Sakthi Vignesh