Can I convert std::vector element pointer to index with this?
http://coliru.stacked-crooked.com/a/cedf3d849539e001
template<class T>
std::size_t get_index(std::vector<T>& vec, T* ptr){
const std::size_t i = ptr - &(*vec.begin());
return i;
}
If elements in vector is guaranteed to be contiguous, then I think we can do such pointer arithmetic... Or no?
Vector elements are stored contiguously, yes. You can also use std::vector<T>::data() instead of &*std::vector<T>::begin().
You can read more at: http://en.cppreference.com/w/cpp/container/vector
PS: There is already a question about this - Are std::vector elements guaranteed to be contiguous?
If elements in vector is guaranteed to be contiguous, then I think we can do such pointer arithmetic...
Elements in vector are guaranteed to be contiguous, and you can use such pointer arithmetic indeed.
However, there is a caveat: addressof operator can be overloaded to return something other than the address. If you cannot guarantee that it won't be overloaded, use std::addressof instead.
Or simply use std::vector::data as shown by Ivan.
Related
This is an undefined behavior:
std::vector<int> v;
int const * a = &v[0];
My goal is to avoid the UB and the vector::data() function would work. But I need to do it without >=C++11.
For example, if I were to allocate some memory with vector::reserve, would it work?
v.reserve(1);
int const * a = &v[0];
Clarification:
The vector is not changed after the point I take the pointer and the vector may be empty or contain data.
Just perform the check inside a conditional operator:
int const * a = v.empty() ? NULL : &v[0];
This has the added benefit over data() that you can check from the pointer itself whether the vector was empty: if it was, a is null.
Vectors don't provide any guarantees of the pointers of their elements. It's very dangerous to use that reserve you did, because you may push_back() some element later, which may invalidate your pointer.
If you want a better story, consider that even iterators may be invalidated with push_back and erase... why would a pointer still remain valid at all?
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.
I've got a std::vector and I need to get the hash of its contents from libgcrypt.
How do I get the contents of std::vector<int-type> vec into gcry_md_hash_buffer(GCRY_MD_MD5, (void*)&digest, (void*)buffer, vec.size()); where buffer is the data in vec?
If you are using C++11, pass
vec.data()
for buffer.
Reference: Vector::data()
If not, pass &(vec.front()). The elements of vec are guaranteed to be in contiguous storage.
What does the function gcry_md_hash_buffer() expect of buffer? Is it supposed to be an array of int? If yes, you can pass &vec[0] or vec.data() - std::vector guarantees that underlying representation of data is the same as in a C array.
You can also use std::vector::operator[] (the index operator), and the address-of (&) operator:
&(buffer[0])
The above first gets a reference to the first element of the vector (buffer[0]), the takes its address &(...).
Using it in the hashing function,
gcry_md_hash_buffer(GCRY_MD_MD5, (void*)&digest, (void*)(&(buffer[0])), vec.size());
// ^^^^^^^^^^^^
Note that many of the parentheses are unecessary, though I normally put them to eliminate the risk of ambiguity and possible errors.
I have a vector of structs, like so: std::vector<mystruct> elems.
If I then have a mystruct pointer, which I know is pointing to one of the elements of elems, how can I get its index within elems?
ptr - &elems[0];
As of C++03, vector storage is required to be contiguous, and the definition of "contiguous" in the standard is that &v[n] == &v[0] + n;
[Edit: from a fairly theoretical portability point of view, beware that implementations are permitted to define SIZE_MAX and ptrdiff_t such that it's possible to subtract two pointers within the same object with undefined result. You'd hope that no implementation will arrange for that to actually cause problems, but you never know. It's fairly easy for the implementation to avoid - just don't return allocations that big]
Elements must be stored contiguously. Therefore:
mystruct * elem; // definitely within the vector
mystruct * first = &elems[0];
std::vector<mystruct>::size_type index = elem - first;
technically though should use ptrdiff_t rather than size_type to subtract pointers.
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.