Jak uzyskać wskaźnik std :: vector do surowych danych?

160

Próbuję użyć std::vector jako chartablicy.

Moja funkcja przyjmuje void pointer:

void process_data(const void *data);

Wcześniej po prostu użyłem tego kodu:

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

Który działał zgodnie z oczekiwaniami.

Ale teraz potrzebuję dynamiki std::vector, więc zamiast tego wypróbowałem ten kod:

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

Pytanie brzmi, jak przekazać wektor char do mojej funkcji, aby uzyskać dostęp do surowych danych wektorowych (bez względu na to, jaki to format - elementy zmiennoprzecinkowe itp.)?

Próbowałem tego:

process_data(&something);

I to:

process_data(&something.begin());

Ale wrócił wskaźnik do danych bełkot, a ten ostatni dał ostrzeżenie: warning C4238: nonstandard extension used : class rvalue used as lvalue.

Rekrut
źródło

Odpowiedzi:

238

&somethingpodaje adres std::vectorobiektu, a nie adres przechowywanych danych. &something.begin()podaje adres iteratora zwrócony przez begin()(jak ostrzega kompilator, nie jest to technicznie dozwolone, ponieważ something.begin()jest to wyrażenie rvalue, więc jego adresu nie można pobrać).

Zakładając, że kontener ma co najmniej jeden element, musisz uzyskać adres początkowego elementu kontenera, który możesz uzyskać za pośrednictwem

  • &something[0]lub &something.front()(adres elementu pod indeksem 0), lub

  • &*something.begin()(adres elementu wskazywanego przez iterator zwracany przez begin()).

C ++ 11, nową funkcję element dodano std::vector: data(). Ta funkcja członkowska zwraca adres początkowego elementu w kontenerze, podobnie jak &something.front(). Zaletą tej funkcji składowej jest to, że można ją wywołać, nawet jeśli kontener jest pusty.

James McNellis
źródło
103
Ważne Strzeż się, vector<bool>który jest wyjątkiem od tej odpowiedzi (i nie ma ciągłej pamięci bools).
Motti
18
Z drugiej strony nie ma się na co uważać: wszystkie trzy metody nie będą się skompilować, std::vector<bool>ponieważ std::vector<bool>wymaga użycia obiektu proxy, a tego proxy nie można niejawnie przekonwertować na plik bool*. Aby obejść ten problem, jeśli potrzebujesz sekwencji bool, najlepiej po prostu użyć pliku std::vector<char>. @Motti
James McNellis
To prawda, uwaga była ogólnie i nie była skierowana jako twoja odpowiedź, ponieważ nie ma ciągłego przechowywania pamięci, nie ma sposobu, aby się do tego dostać.
Motti
7
za bycie wszechstronnym, ale głównie za .data()- po prostu udam, że nie widziałem tego brzydkiego &*iterator: P
underscore_d
2
jak długo wskaźnik wróci z data()transmisji? Jeśli rozmiar wektora nigdy nie zostanie zmieniony ani na większy, ani na mniejszy (za pośrednictwem push_back()lub innych funkcji, w tym reserve), czy gwarantuje się, że wskaźnik będzie żył tak długo, jak będzie żył wektor, wskazując właściwe miejsce?
johnbakers
81

something.data() zwróci wskaźnik do przestrzeni danych wektora.

Chris Dodd
źródło
error C2039: 'data' : is not a member of 'std::vector<_Ty>'
Rookie
2
@Rookie: wygląda na to, że używasz zepsutego kompilatora - 23.3.6.3 w specyfikacji C ++ definiuje vector :: data. Spróbuj zgłosić błąd u dostawcy lub uzyskaj lepszy kompilator.
Chris Dodd
1
@Chris Dodd Mam ten sam błąd. Używam Visual Studio 2008.
bodacydo
34
@ChrisDodd: vector::data()jest nowy w C ++ 11
HighCommander4
Używam Visual Studio 2012 i musieli dodać vector :: data (), ponieważ używam go dużo.
Robert Snyder
12

Zamiast tego weź wskaźnik do pierwszego elementu:

process_data (&something [0]);
Steven Don
źródło
Myślałem, że zwróci adres pamięci pierwszej pozycji nawet bez nawiasów dolnych?
Tim
Dotyczy to tablic, a nie wektorów.
Steven Don
Właśnie to sobie uświadomiłem, przepraszam.
Tim