Як отримати std :: векторний покажчик на необроблені дані?


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);

Питання полягає в тому, як я можу передати вектор char на свою функцію, щоб я мав доступ до векторних необроблених даних (незалежно від того, у якому форматі це - плаває тощо)?

Я спробував це:

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>що це виняток з цієї відповіді (і не має суміжного сховища пам'яті bool).
Мотті

18
З іншого боку, слід не надто остерігатися: усі три ці способи не вдасться компілювати, std::vector<bool>оскільки std::vector<bool>вимагається використання проксі-об'єкта, і цей проксі не може бути неявно перетворений у bool*. Як вирішення цього питання, якщо вам потрібна послідовність bool, найкраще просто використовувати std::vector<char>. @Motti
James McNellis

Щоправда, остерігайтеся взагалі і не спрямовано як вашу відповідь, оскільки немає суміжного сховища пам’яті, немає способу дійти до цього.
Мотті

7
для того, щоб бути всеосяжним, але в основному для .data()- я просто роблю вигляд, що не бачив цього потворного &*iterator: P
підкреслюю

2
як довго вказівник повернеться з data()прямої трансляції? Якщо вектор ніколи не змінюється чи більшим, чи меншим (через push_back()або інші функції, включаючи reserve), чи гарантується, що покажчик буде жити так довго, як живе вектор, вказуючи на правильне місце?
johnbakers

81

something.data() поверне вказівник на простір даних вектора.


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

2
@Rookie: схоже, ви використовуєте зламаний компілятор - 23.3.6.3 у специфікації C ++ визначає вектор :: data. Спробуйте подати помилку у свого постачальника або отримайте кращий компілятор.
Кріс Додд

1
@Chris Dodd У мене така ж помилка. Я використовую Visual Studio 2008.
bodacydo

34
@ChrisDodd: новачка vector::data()для C ++ 11
HighCommander4

Я використовую Visual Studio 2012, і вони, мабуть, додали вектор :: data (), тому що я використовую це купу.
Роберт Снайдер

12

Візьміть замість цього вказівник на перший елемент:

process_data (&something [0]);

Я думав, що це поверне адресу пам'яті першого елемента навіть без дужок підписки?
Тім

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

Так просто зрозумів, вибач.
Тім
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.