3

I have a vector of chars and I want to pass it's content as a char* to another function:

void foo(boost::shared_ptr<std::vector<boost::uint8_t> > data)
{
    bar(data->size()?reinterpret_cast<char*>(&(data.get()->front())):NULL);
}

Can I assume that the data is always stored in a contiguous manner? Thanks.

Sanich
  • 1,739
  • 6
  • 25
  • 43
  • 2
    You mean *contiguous*? Yes. – Nim Feb 25 '14 at 12:07
  • 1
    Yes, vector elements are contiguous, if you use c++11 you can also use the function [`T* data`](http://en.cppreference.com/w/cpp/container/vector/data) instead of the ugly cast to pass the underlying array to another function. – pan- Feb 25 '14 at 13:01

3 Answers3

6

From the n2798 (draft of C++0x)::

23.2.6 Class template vector [vector]

1 A vector is a sequence container that supports random access iterators. In addition, it supports (amortized) constant time insert and erase operations at the end; insert and erase in the middle take linear time. Storage management is handled automatically, though hints can be given to improve efficiency. The elements of a vector are stored contiguously, meaning that if v is a vector where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().

Also do check array being reallocated (invalidating any pointers and iterators) after adding elements to it.

Also check this article:- Cringe not: Vectors are guaranteed to be contiguous

contiguity is in fact part of the vector abstraction. It’s so important, in fact, that when it was discovered that the C++98 standard didn’t completely guarantee contiguity, the C++03 standard was amended to explicitly add the guarantee.

Also from the C++ FAQ

#include <vector>
#include "Foo.h"  /* get class Foo */

// old-style code that wants an array
void f(Foo* array, unsigned numFoos);

void g()
{
  std::vector<Foo> v;
  ...
  f(v.empty() ? NULL : &v[0], v.size());  ← safe
}

The funny expression v.empty() ? NULL : &v[0] simply passes the NULL pointer if v is empty, otherwise passes a pointer to the first (zeroth) element of v. If you know a priori that v is not empty, you can change that to simply &v[0]. In general, it means you are guaranteed that &v[0] + n == &v[n], where v is a std::vector<T> and n is an integer in the range 0 .. v.size()-1.

However v.begin() is not guaranteed to be a T*, which means v.begin() is not guaranteed to be the same as &v[0]:

void g()
{
  std::vector<Foo> v;
  ...
  f(v.begin(), v.size());  ← Error!! Not Guaranteed!!
    ^^^^^^^^^-- cough, choke, gag; not guaranteed to be the same as &v[0]
}
Community
  • 1
  • 1
Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
  • Note that the inequality is actually ` 0<= n <= v.size()` since you are allowed to read the pointer one beyond the end of the vector, but just don't attempt to dereference it. And the notation `&v[n]` is not permitted to dereference. – Bathsheba Oct 15 '22 at 20:41
3

From Cppreference:

std::vector is a sequence container that encapsulates dynamic size arrays.

The elements are stored contiguously, which means that elements can be accessed not only through iterators, but also using offsets on regular pointers to elements.

So yes, the elements are contiguous in memory. That means you can use the underlying data container (which is a T[], that you get with the data() member function) as a classic array.

Community
  • 1
  • 1
JBL
  • 12,588
  • 4
  • 53
  • 84
0

Yes you can. The standard mandates that the memory in a std::vector is contiguous. But note that this is not true for std::vector<bool>.

In fact std::vector::data() gives you a pointer to the first element in the vector. You can then use pointer arithmetic to access the vector elements.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483