How to get std::vector pointer to the raw data?
Asked Answered
C

3

185

I'm trying to use std::vector as a char array.

My function takes in a void pointer:

void process_data(const void *data);

Before I simply just used this code:

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

Which worked as expected.

But now I need the dynamicity of std::vector, so I tried this code instead:

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

The question is, how do I pass the char vector to my function so I can access the vector raw data (no matter which format it is – floats, etc.)?

I tried this:

process_data(&something);

And this:

process_data(&something.begin());

But it returned a pointer to gibberish data, and the latter gave warning: warning C4238: nonstandard extension used : class rvalue used as lvalue.

Cohla answered 26/6, 2011 at 17:24 Comment(0)
D
278

&something gives you the address of the std::vector object, not the address of the data it holds. &something.begin() gives you the address of the iterator returned by begin() (as the compiler warns, this is not technically allowed because something.begin() is an rvalue expression, so its address cannot be taken).

Assuming the container has at least one element in it, you need to get the address of the initial element of the container, which you can get via

  • &something[0] or &something.front() (the address of the element at index 0), or

  • &*something.begin() (the address of the element pointed to by the iterator returned by begin()).

In C++11, a new member function was added to std::vector: data(). This member function returns the address of the initial element in the container, just like &something.front(). The advantage of this member function is that it is okay to call it even if the container is empty.

Dagda answered 26/6, 2011 at 17:27 Comment(8)
Important Beware of vector<bool> which is the exception to this answer (and doesn't have a contiguous memory storage of bools).Excretory
On the bright side, there's not much to beware of: all three of these methods will fail to compile with std::vector<bool> because std::vector<bool> requires the use of a proxy object and that proxy can't be implicitly converted to a bool*. As the workaround for this, if you do need a sequence of bool, it's best just to use a std::vector<char>. @ExcretoryDagda
True, the beware was in general and not directed as your answer, since there is no contiguous memory storage there is no way to get at it.Excretory
up for being comprehensive but mainly for .data() - I'lll just pretend I didn't see that ugly &*iterator :PPeriderm
how long will the pointer returned from data() live? If the vector is never resized either larger or smaller (via push_back() or other functions, including reserve), is it guaranteed that the pointer will live as long as the vector lives, pointing to the correct place?Dahlberg
FYI, Scott Meyer's book "Effective STL" (for C++98) covers this topic in great depth in "Item 16: Know how to pass vector and string data to legacy APIs".Just
Note that it is indeed safe to call data() on an empty vector, but its result is mostly useless. It will point to some memory, even though there are no elements in the vector which may be unexpected.Implosive
@Dahlberg For your concerns, std::vector::reserve is the only way to make sure the pointers are valid even when adding items to the container. Otherwise, you will get dangling pointers.Tycoon
T
97

something.data() will return a pointer to the data space of the vector.

Tintype answered 26/6, 2011 at 19:8 Comment(6)
error C2039: 'data' : is not a member of 'std::vector<_Ty>'Cohla
@Rookie: looks like you're using a broken compiler -- 23.3.6.3 in the C++ spec defines vector::data. Try filing a bug with your vendor or getting a better compiler.Tintype
@Chris Dodd I've the same error. I'm using Visual Studio 2008.Adrial
@ChrisDodd: vector::data() is new to C++11Gentile
I use Visual Studio 2012 and they must have added the vector::data() because I use it a bunch.Kellsie
I liked sth.data() but recently I have to roll back to &sth.front(). We have a system that only supports g++34 ...Impudent
V
13

Take a pointer to the first element instead:

process_data (&something [0]);
Variometer answered 26/6, 2011 at 17:25 Comment(3)
I thought that it would return the memory address of the first item even without the subscript brackets?Gorlicki
That's for arrays, not for vectors.Variometer
Yeah just realized that, sorry.Gorlicki

© 2022 - 2024 — McMap. All rights reserved.