Is data storage in std::vector continuous? [duplicate] - c++

This question already has answers here:
Are std::vector elements guaranteed to be contiguous?
(7 answers)
Closed 9 years ago.
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.

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]
}

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.

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.

Related

Is the vector reserved space always linerar? [duplicate]

My question is simple: are std::vector elements guaranteed to be contiguous? In other words, can I use the pointer to the first element of a std::vector as a C-array?
If my memory serves me well, the C++ standard did not make such guarantee. However, the std::vector requirements were such that it was virtually impossible to meet them if the elements were not contiguous.
Can somebody clarify this?
Example:
std::vector<int> values;
// ... fill up values
if( !values.empty() )
{
int *array = &values[0];
for( int i = 0; i < values.size(); ++i )
{
int v = array[i];
// do something with 'v'
}
}
This was missed from C++98 standard proper but later added as part of a TR. The forthcoming C++0x standard will of course contain this as a requirement.
From 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().
As other answers have pointed out, the contents of a vector is guaranteed to be continuous (excepting bool's weirdness).
The comment that I wanted to add, is that if you do an insertion or a deletion on the vector, which could cause the vector to reallocate it's memory, then you will cause all of your saved pointers and iterators to be invalidated.
The standard does in fact guarantee that a vector is continuous in memory and that &a[0] can be passed to a C function that expects an array.
The exception to this rule is vector<bool> which only uses one bit per bool thus although it does have continuous memory it can't be used as a bool* (this is widely considered to be a false optimization and a mistake).
BTW, why don't you use iterators? That's what they're for.
As other's have already said, vector internally uses a contiguous array of objects. Pointers into that array should be treated as invalid whenever any non-const member function is called IIRC.
However, there is an exception!!
vector<bool> has a specialised implementation designed to save space, so that each bool only uses one bit. The underlying array is not a contiguous array of bool and array arithmetic on vector<bool> doesn't work like vector<T> would.
(I suppose it's also possible that this may be true of any specialisation of vector, since we can always implement a new one. However, std::vector<bool> is the only, err, standard specialisation upon which simple pointer arithmetic won't work.)
I found this thread because I have a use case where vectors using contiguous memory is an advantage.
I am learning how to use vertex buffer objects in OpenGL. I created a wrapper class to contain the buffer logic, so all I need to do is pass an array of floats and a few config values to create the buffer.
I want to be able to generate a buffer from a function based on user input, so the length is not known at compile time. Doing something like this would be the easiest solution:
void generate(std::vector<float> v)
{
float f = generate_next_float();
v.push_back(f);
}
Now I can pass the vector's floats as an array to OpenGL's buffer-related functions. This also removes the need for sizeof to determine the length of the array.
This is far better than allocating a huge array to store the floats and hoping I made it big enough, or making my own dynamic array with contiguous storage.
cplusplus.com:
Vector containers are implemented as dynamic arrays; Just as regular arrays, vector containers have their elements stored in contiguous storage locations, which means that their elements can be accessed not only using iterators but also using offsets on regular pointers to elements.
Yes, the elements of a std::vector are guaranteed to be contiguous.

Does each element in a vector have a unique memory address?

Fairly new to C++. Referring to this snippet of code:
for (std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
In particular when initializing the iterator and the end condition. Does each element in the vector have a unique memory address to point to? Or do iterators work differently than pointers?
Although iterators are not necessarily pointers (although for std::vectors most non-debug implementations implement them as thin wrappers around pointers), std::vector is guaranteed to have its elements contiguous in memory. Which implies that YES, every element has a distinct memory location.
Every object (that exists at a particular time) has a unique address. The elements of a vector are objects (with the exception of the abomination which is the std::vector<bool> specialization). So yes, they all have unique addresses. Keep in mind though, that when you add elements to a vector, it may reallocate. And when it reallocates, all the old objects are destroyed and moved to new objects with different addresses, and the old memory is free to be reused, perhaps by further reallocations of the same vector. The following is possible, for example:
std::vector<int> v;
v.push_back(0);
std::intptr_t a0 = (std::intptr_t)&v[0];
v.push_back(1); // a reallocation may happen here
v.push_back(2); // and perhaps another one here
std::intptr_t a2 = (std::intptr_t)&v[2];
if (a0 == a2) {
std::cout << "This code is unlikely to be executed, but technically possible.";
}
Each element does indeed have a unique address in memory. Basically, let's look at this sample vector:
template <class T>
class vec
{
public:
vec() ;
~vec() ;
T * elements;
}
You can see here is just an example of a vector. So what the iterators do is point to each pointer in the element. They may not have a unique address themselves, but they point to each element in the vector. So each iterator has UNIQUE memory addresses.
And like I said in my comments, they can't work differently since the Vectors and their iterators are libraries made by people like you, using C++. They can't work differently from pointers which are built in the C++ language.
Also from references: (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<T, Allocator> where T is some type other
than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().
From [vector.overview]/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<T, Allocator> where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().
Emphasis mine
So since &v[n] is valid for for all n in [0, size()) then ever element in the vector has its own unique address.

Is it safe to pass a pointer to the first element in a vector when an array is expected? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can I call functions that take an array/pointer argument using a std::vector instead?
I recently came across something like this:
class X {
public: void foo(float* p, int elements);
};
= a method that expects an array of float values.
But in the example code this was the way they used it:
std::vector<float> bar;
bar.push_back(42);
// ...
X x;
x.foo( &bar[0], (int)bar.size() );
Now I'm wondering whether this is a safe method or just happens to work with most implementations of std::vector? (maybe this is an operator-overloading thing? I'm not yet that confident with this stuff..)
Yes, it's safe.
n3337 23.3.6.1/1. In C++03 standard this is 23.2.4/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().
Yes it is allowable and will work as Forever points out. However, it is safe only for so long as you take care not to delete vector and leave a dangling pointer in the array. Since you are sharing memory between the array and the vector, it is up to you to manage that memory.
from here:
As such, their elements are ordered following a strict linear sequence.
using that definition and the element access operator ([]), then expression &avector[0] gets the address of the first element, and the next elements are contiguous sequence after it.

Are std::vector elements guaranteed to be contiguous?

My question is simple: are std::vector elements guaranteed to be contiguous? In other words, can I use the pointer to the first element of a std::vector as a C-array?
If my memory serves me well, the C++ standard did not make such guarantee. However, the std::vector requirements were such that it was virtually impossible to meet them if the elements were not contiguous.
Can somebody clarify this?
Example:
std::vector<int> values;
// ... fill up values
if( !values.empty() )
{
int *array = &values[0];
for( int i = 0; i < values.size(); ++i )
{
int v = array[i];
// do something with 'v'
}
}
This was missed from C++98 standard proper but later added as part of a TR. The forthcoming C++0x standard will of course contain this as a requirement.
From 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().
As other answers have pointed out, the contents of a vector is guaranteed to be continuous (excepting bool's weirdness).
The comment that I wanted to add, is that if you do an insertion or a deletion on the vector, which could cause the vector to reallocate it's memory, then you will cause all of your saved pointers and iterators to be invalidated.
The standard does in fact guarantee that a vector is continuous in memory and that &a[0] can be passed to a C function that expects an array.
The exception to this rule is vector<bool> which only uses one bit per bool thus although it does have continuous memory it can't be used as a bool* (this is widely considered to be a false optimization and a mistake).
BTW, why don't you use iterators? That's what they're for.
As other's have already said, vector internally uses a contiguous array of objects. Pointers into that array should be treated as invalid whenever any non-const member function is called IIRC.
However, there is an exception!!
vector<bool> has a specialised implementation designed to save space, so that each bool only uses one bit. The underlying array is not a contiguous array of bool and array arithmetic on vector<bool> doesn't work like vector<T> would.
(I suppose it's also possible that this may be true of any specialisation of vector, since we can always implement a new one. However, std::vector<bool> is the only, err, standard specialisation upon which simple pointer arithmetic won't work.)
I found this thread because I have a use case where vectors using contiguous memory is an advantage.
I am learning how to use vertex buffer objects in OpenGL. I created a wrapper class to contain the buffer logic, so all I need to do is pass an array of floats and a few config values to create the buffer.
I want to be able to generate a buffer from a function based on user input, so the length is not known at compile time. Doing something like this would be the easiest solution:
void generate(std::vector<float> v)
{
float f = generate_next_float();
v.push_back(f);
}
Now I can pass the vector's floats as an array to OpenGL's buffer-related functions. This also removes the need for sizeof to determine the length of the array.
This is far better than allocating a huge array to store the floats and hoping I made it big enough, or making my own dynamic array with contiguous storage.
cplusplus.com:
Vector containers are implemented as dynamic arrays; Just as regular arrays, vector containers have their elements stored in contiguous storage locations, which means that their elements can be accessed not only using iterators but also using offsets on regular pointers to elements.
Yes, the elements of a std::vector are guaranteed to be contiguous.

Is it safe to assume that STL vector storage is always contiguous?

If you have an STL vector which has been resized, is it safe to take the address of element 0 and assume the rest of the vector will follow in memory?
e.g.
vector<char> vc(100);
// do some stuff with vc
vc.resize(200);
char* p = &vc[0];
// do stuff with *p
Yes, that is a valid assumption (*).
From the C++03 standard (23.2.4.1):
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().
(*) ... but watch out for the array being reallocated (invalidating any pointers and iterators) after adding elements to it.
The C++03 standard added wording to make it clear that vector elements must be contiguous.
C++03 23.2.4 Paragraph 1 contains the following language which is not in the C++98 standard document:
The elements of a vector are stored
contiguously, meaning that if v is a
vector<T, Allocator> where T is
some type other than bool, then it
obeys the identity &v[n] == &v[0] +
n for all 0 <= n < v.size().
Herb Sutter talks about this change in one of his blog entries, 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.
Storage is always contiguous, but it may move as the vector's capacity is changed.
If you had a pointer, reference, or iterator on element zero (or any element) before a capacity-changing operation, it is invalidated and must be reassigned.
Yes it's contiguous
std::vector guarantees that the items are stored in a contiguous array, and is therefore the preferred replacement of arrays and can also be used to interface with platform-dependent low-level code (like Win32 API calls). To get a pointer to the array use:
&myVector.front();
yes.
it should alway be contiguous