7

How can I access the contiguous memory buffer used within a std::vector so I can perform direct memory operations on it (e.g. memcpy)? Also, it is safe to perform operations like memcpy on that buffer?

I've read that the standard guarantees that a vector uses a contiguous memory buffer internally, but that it is not necessarily implemented as a dynamic array. I figure given that it is definitely contiguous, I should be able to use it as such - but I wasn't sure if the vector implementation stored book-keeping data as part of that buffer. If it did, then something like memcpying the vector buffer would destroy its internal state.

John Humphreys
  • 37,047
  • 37
  • 155
  • 255
  • possible duplicate of [Is it safe to assume that STL vector storage is always contiguous?](http://stackoverflow.com/questions/247738/is-it-safe-to-assume-that-stl-vector-storage-is-always-contiguous) – Bo Persson Aug 30 '11 at 20:56
  • 2
    @Bo, may not be a dup as the OP here asks specifically about C std lib functions whereas the linked question does not. – Doug T. Aug 30 '11 at 20:59
  • The dup shows `char* p = &vc[0]` as the way to get at the buffer. Then what? – Bo Persson Aug 30 '11 at 21:03

7 Answers7

16

In practice, virtually all compilers implement vector as an array under the hood. You can get a pointer to this array by doing &somevector[0]. If the contents of the vector are POD ('plain-old-data') types, doing memcpy should be safe - however if they're C++ classes with complex initialization logic, you'd be safer using std::copy.

bdonlan
  • 224,562
  • 31
  • 268
  • 324
10

Simply do

&vec[0];

// or Goz's suggestion:
&vec.front();

// or
&*vec.begin();
// but I don't know why you'd want to do that

This returns the address of the first element in the vector (assuming vec has more than 0 elements), which is the address of the array it uses. vector storage is guaranteed by the standard to be contiguous, so this is a safe way to use a vector with functions that expect arrays.

Be aware that if you add, or remove elements from the vector, or [potentially] modify the vector in any way (such as calling reserve), this pointer could become invalid and point to a deallocated area of memory.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
6

You can simply do:

  &vect[0]

The memory is guaranteed contiguous so its safe to work with it with C library functions such as memcpy. However, you shouldn't persist pointers into the contiguous data because vector resizes may reallocate and copy the memory to a different location. IE the following would be bad:

  std::vector<char> charVect;
  // insert a bunch of stuff into charVect
  ...
  char* bufferPtr = &charVect[0];
  charVect.push_back('a'); // potential resize
  // Now bufferPtr may not be valid since the resize may have moved
  // the vectors contents
  bufferPtr[0] = 'f'; // **CRASH**
Doug T.
  • 64,223
  • 27
  • 138
  • 202
2
&myvec[0]

But note that using memcpy is really only applicable if this is a vector of PODs or primitive types. Doing direct memory manipulation of anything else leads to undefined behaviour.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
2

The simplest way is to use &v[0], where v is your vector. An example:

int write_vector(int fd, const std::vector<char>& v) {
   int rval = write(fd, &v[0], v.size());
   return rval;
}
Dave S
  • 20,507
  • 3
  • 48
  • 68
1

Yes - since the standard guarantees contiguous placement of the vector's internal data, you can access a pointer to the first element in the vector via:

std::vector<int> my_vector;
// initialize...

int* arr = &my_vector[0];
Dawson
  • 2,673
  • 1
  • 16
  • 18
0

While you can safely read the right amount of data from the underlying storage, writing there may not happen to be a good idea, depending on the design.

    vlad:Code ⧴ cat vectortest.cpp
    #include <vector>
    #include <iostream>
    int main()
    {
        using namespace std;
        vector<char> v(2);
        v.reserve(10);
        char c[6]={ 'H', 'e', 'l', 'l', 'o', '\0' };
        cout << "Original size is " << v.size();
        memcpy( v.data(), c, 6);
        cout << ", after memcpy it is " << v.size();
        copy(c, c+6, v.begin());
        cout << ", and after copy it is " << v.size() << endl;
        cout << "Arr: " << c << endl;
        cout << "Vec: ";
        for (auto i = v.begin(); i!=v.end(); ++i) cout << *i;
        cout << endl;
    }
    vlad:Code ⧴ make vectortest
    make: `vectortest' is up to date.
    vlad:Code ⧴ ./vectortest
    Original size is 2, after memcpy it is 2, and after copy it is 2
    Arr: Hello
    Vec: He
    vlad:Code ⧴

So if you are writing past the size(), then the new data is not accessible by class methods.

You can account for that and ensure the size is enough (e.g. vector<char> v(10)), but do you really want to make software where you are fighting the standard library?

Vlad Didenko
  • 4,481
  • 4
  • 25
  • 34