Як отримати 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.