Comment obtenir le pointeur std :: vector vers les données brutes?

160

J'essaye d'utiliser std::vectorcomme chartableau.

Ma fonction prend un pointeur vide:

void process_data(const void *data);

Avant, je viens d'utiliser ce code:

char something[] = "my data here";
process_data(something);

Ce qui a fonctionné comme prévu.

Mais maintenant, j'ai besoin de la dynamicité de std::vector, alors j'ai essayé ce code à la place:

vector<char> something;
*cut*
process_data(something);

La question est, comment puis-je passer le vecteur char à ma fonction pour pouvoir accéder aux données brutes vectorielles (quel que soit le format - flottants, etc.)?

J'ai essayé ceci:

process_data(&something);

Et ça:

process_data(&something.begin());

Mais il est revenu un pointeur vers des données charabia, et celui - ci a donné avertissement: warning C4238: nonstandard extension used : class rvalue used as lvalue.

Débutant
la source

Réponses:

238

&somethingvous donne l'adresse de l' std::vectorobjet, pas l'adresse des données qu'il contient. &something.begin()vous donne l'adresse de l'itérateur retourné par begin()(comme l'avertit le compilateur, cela n'est pas autorisé techniquement car il something.begin()s'agit d'une expression rvalue, donc son adresse ne peut pas être prise).

En supposant que le conteneur contient au moins un élément, vous devez obtenir l'adresse de l'élément initial du conteneur, que vous pouvez obtenir via

  • &something[0]ou &something.front()(l'adresse de l'élément à l'index 0), ou

  • &*something.begin()(l'adresse de l'élément pointé par l'itérateur renvoyé par begin()).

En C ++ 11, une nouvelle fonction de membre a été ajouté à std::vector: data(). Cette fonction membre renvoie l'adresse de l'élément initial dans le conteneur, tout comme &something.front(). L'avantage de cette fonction membre est qu'il est possible de l'appeler même si le conteneur est vide.

James McNellis
la source
103
Important Méfiez-vous de vector<bool>qui est l'exception à cette réponse (et n'a pas de stockage de mémoire contigu de bools).
Motti
18
Du bon côté, il n'y a pas grand-chose à se méfier: ces trois méthodes ne pourront pas être compilées std::vector<bool>car elles std::vector<bool>nécessitent l'utilisation d'un objet proxy et ce proxy ne peut pas être implicitement converti en bool*. Pour contourner ce problème, si vous avez besoin d'une séquence de bool, il est préférable d'utiliser simplement un fichier std::vector<char>. @Motti
James McNellis
Certes, la méfiance était en général et non dirigée comme votre réponse, car il n'y a pas de stockage mémoire contigu, il n'y a aucun moyen d'y accéder.
Motti le
7
pour être complet mais surtout pour .data()- je vais juste faire comme si je n'avais pas vu ça moche &*iterator: P
underscore_d
2
combien de temps le pointeur reviendra-t-il du data()live? Si le vecteur n'est jamais redimensionné ni plus grand ni plus petit (via push_back()ou d'autres fonctions, y compris reserve), est-il garanti que le pointeur vivra aussi longtemps que le vecteur vit, pointant vers le bon endroit?
johnbakers
81

something.data() renverra un pointeur vers l'espace de données du vecteur.

Chris Dodd
la source
error C2039: 'data' : is not a member of 'std::vector<_Ty>'
Rookie
2
@Rookie: on dirait que vous utilisez un compilateur cassé - 23.3.6.3 dans la spécification C ++ définit vector :: data. Essayez de déposer un bogue auprès de votre fournisseur ou d'obtenir un meilleur compilateur.
Chris Dodd
1
@Chris Dodd J'ai la même erreur. J'utilise Visual Studio 2008.
bodacydo
34
@ChrisDodd: vector::data()nouveau sur C ++ 11
HighCommander4
J'utilise Visual Studio 2012 et ils doivent avoir ajouté le vector :: data () car je l'utilise beaucoup.
Robert Snyder
12

Prenez plutôt un pointeur vers le premier élément:

process_data (&something [0]);
Steven Don
la source
Je pensais qu'il retournerait l'adresse mémoire du premier élément même sans les crochets d'indice?
Tim
C'est pour les tableaux, pas pour les vecteurs.
Steven Don
Ouais je viens de m'en rendre compte, désolé.
Tim