Come ottenere il puntatore std :: vector ai dati grezzi?


160

Sto provando a usare std::vector come un chararray.

La mia funzione assume un puntatore vuoto:

void process_data(const void *data);

Prima ho semplicemente usato questo codice:

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

Che ha funzionato come previsto.

Ma ora ho bisogno della dinamicità di std::vector, quindi ho provato questo codice invece:

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

La domanda è: come faccio a passare il carattere char alla mia funzione in modo da poter accedere ai dati grezzi del vettore (indipendentemente dal formato: float, ecc.)?

Ho provato questo:

process_data(&something);

E questo:

process_data(&something.begin());

Ma è restituito un puntatore ai dati senza senso, e quest'ultimo ha dato avvertimento: warning C4238: nonstandard extension used : class rvalue used as lvalue.

Risposte:


238

&somethingti dà l'indirizzo std::vectordell'oggetto, non l'indirizzo dei dati che contiene. &something.begin()ti dà l'indirizzo dell'iteratore restituito da begin()(come avverte il compilatore, questo non è tecnicamente permesso perché something.begin()è un'espressione rvalue, quindi il suo indirizzo non può essere preso).

Supponendo che il contenitore contenga almeno un elemento, è necessario ottenere l'indirizzo dell'elemento iniziale del contenitore, che è possibile ottenere tramite

  • &something[0]o &something.front()(l'indirizzo dell'elemento all'indice 0), oppure

  • &*something.begin()(l'indirizzo dell'elemento indicato dall'iteratore restituito da begin()).

In C ++ 11, una nuova funzione membro è stato aggiunto al std::vector: data(). Questa funzione membro restituisce l'indirizzo dell'elemento iniziale nel contenitore, proprio come &something.front(). Il vantaggio di questa funzione membro è che è possibile chiamarlo anche se il contenitore è vuoto.


103
Importante Fai attenzione a vector<bool>quale è l'eccezione a questa risposta (e non ha una memoria contigua di bools).
Motti,

18
Il lato positivo è che non bisogna fare molta attenzione: tutti e tre questi metodi non verranno compilati std::vector<bool>perché std::vector<bool>richiede l'uso di un oggetto proxy e tale proxy non può essere convertito implicitamente in a bool*. Come soluzione alternativa per questo, se hai bisogno di una sequenza di bool, è meglio usare solo a std::vector<char>. @Motti
James

È vero, il diffidare era in generale e non diretto come la tua risposta, poiché non esiste memoria contigua per la memoria, non c'è modo di ottenerla.
Motti,

7
per essere comprensivo ma soprattutto per .data()- farò solo finta di non aver visto così brutto &*iterator: P
underscore_d

2
per quanto tempo il puntatore tornerà dal data()vivo? Se il vettore non viene mai ridimensionato né più grande né più piccolo (tramite push_back()o altre funzioni, incluso reserve), è garantito che il puntatore rimarrà attivo finché il vettore vive, indicando il posto corretto?
johnbakers,

81

something.data() restituirà un puntatore allo spazio dati del vettore.


error C2039: 'data' : is not a member of 'std::vector<_Ty>'
Rookie,

2
@Rookie: sembra che tu stia usando un compilatore rotto - 23.3.6.3 nelle specifiche C ++ definisce vector :: data. Prova a presentare un bug al tuo fornitore o a ottenere un compilatore migliore.
Chris Dodd,

1
@ Chris Dodd ho lo stesso errore. Sto usando Visual Studio 2008.
bodacydo

34
@ChrisDodd: vector::data()è nuovo in C ++ 11
HighCommander4

Uso Visual Studio 2012 e devono aver aggiunto vector :: data () perché lo uso in gruppo.
Robert Snyder,

12

Prendi invece un puntatore al primo elemento:

process_data (&something [0]);

Ho pensato che avrebbe restituito l'indirizzo di memoria del primo elemento anche senza le parentesi graffe?
Tim

Questo è per gli array, non per i vettori.
Steven Don,

Sì, l'ho appena capito, scusa.
Tim
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.