Как получить std :: vector указатель на необработанные данные?


160

Я пытаюсь использовать std::vectorв качестве charмассива.

Моя функция принимает пустой указатель:

void process_data(const void *data);

Прежде чем я просто использовал этот код:

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

Который работал как ожидалось.

Но теперь мне нужна динамичность std::vector, поэтому я попробовал этот код вместо этого:

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

Вопрос в том, как передать вектор символов в мою функцию, чтобы я мог получить доступ к необработанным данным вектора (независимо от того, какой это формат - плавающие и т. Д.)?

Я попробовал это:

process_data(&something);

И это:

process_data(&something.begin());

Но он вернулся указатель на тарабарщину данных, а второй дал предупреждение: warning C4238: nonstandard extension used : class rvalue used as lvalue.

Ответы:


238

&somethingдает вам адрес std::vectorобъекта, а не адрес данных, которые он содержит. &something.begin()дает адрес итератора, возвращаемого begin()(как предупреждает компилятор, это технически не разрешено, поскольку something.begin()является выражением rvalue, поэтому его адрес не может быть получен).

Предполагая, что в контейнере есть хотя бы один элемент, вам нужно получить адрес начального элемента контейнера, который вы можете получить через

  • &something[0]или &something.front()(адрес элемента с индексом 0), или

  • &*something.begin()(адрес элемента, на который указывает итератор, возвращаемый begin()).

В C ++ 11, новая функция члена была добавлена в std::vector: data(). Эта функция-член возвращает адрес начального элемента в контейнере, как &something.front(). Преимущество этой функции-члена в том, что ее можно вызывать, даже если контейнер пуст.


103
Важно! Остерегайтесь, vector<bool>который является исключением из этого ответа (и не имеет непрерывного хранения в памяти bools).
Мотти

18
С другой стороны, опасаться особо нечего: все три из этих методов не смогут скомпилироваться, std::vector<bool>потому что std::vector<bool>требует использования объекта-посредника, и этот прокси не может быть неявно преобразован в a bool*. В качестве обходного пути для этого, если вам нужна последовательность bool, лучше просто использовать std::vector<char>. @Motti
Джеймс МакНеллис,

Правда, остерегайтесь в целом, а не как ваш ответ, так как нет непрерывной памяти, и нет способа добраться до нее.
Мотти

7
для того, чтобы быть всесторонним, но главным образом для .data()- я просто притворюсь, что я не видел это уродливое &*iterator: P
underscore_d

2
как долго указатель вернется из data()живого? Если вектор никогда не изменяется ни больше, ни больше (с помощью push_back()или других функций, в том числе reserve), гарантируется ли, что указатель будет жить так же долго, как и вектор, указывая на правильное место?
Джонбейкерс

81

something.data() вернет указатель на пространство данных вектора.


error C2039: 'data' : is not a member of 'std::vector<_Ty>'
Новобранец

2
@Rookie: похоже, вы используете неработающий компилятор - 23.3.6.3 в спецификации C ++ определяет vector :: data. Попробуйте сообщить об ошибке вашему поставщику или получите лучший компилятор.
Крис Додд

1
@ Крис Додд У меня та же ошибка. Я использую Visual Studio 2008.
bodacydo

34
@ChrisDodd: vector::data()новичок в C ++ 11
HighCommander4

Я использую Visual Studio 2012, и они должны были добавить vector :: data (), потому что я использую это множество.
Роберт Снайдер

12

Вместо этого возьмите указатель на первый элемент:

process_data (&something [0]);

Я думал, что он вернет адрес памяти первого элемента, даже без нижних скобок?
Тим

Это для массивов, а не для векторов.
Стивен Дон,

Да, только что понял, извини.
Тим
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.