Can I cast std::vector<int>* to int*? [duplicate] - c++

This question already has answers here:
How to get std::vector pointer to the raw data?
(3 answers)
Closed 7 years ago.
Let's say I have a std::vector<int>* foo; and I have to use it as int* (array of int, not pointer to an int) for an old C type library PVM. As far as I am concerned this might work since the vector stores it's elements next to each other in memory just like arrays. So I tried (int*)foo, but somehow I get an error which I'm unable to debug, so I think this must be the problem. Any ideas, thoughts, elegant workarounds?

You can't cast the vector directly to an array because the vector object consists of pointers to the array data, not the array data itself, which is dynamically allocated. To access the underlying array, use the data() member function:
std::vector<int> vec;
int *arr = vec.data();
Or
std::vector<int> *vecp = new std::vector<int>;
int *arr = vecp->data();

Yes you can. You should prefer this answer by #ApproachingDarknessFish for using std::vector::data which was introduced in C++11.
However, if you are using an older version of C++ you can just use &foo[0] to get an int* to the start of the container.
See this question for why std::vector::data is preferred over &foo.front() and &foo[0] (both which will produce undefined behaviour if foo is empty!)
Have a look at this this answer regarding the contiguous layout of std::vector memory which references the standard:
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().

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.

is it portable to treat std::vector like array [duplicate]

This question already has an answer here:
Can std::vector be treated like an array
(1 answer)
Closed 9 years ago.
I have seen people in my team writing code like this. I personally think this is not portable since vector could be implemented in a totally different way. Am I right?
vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
int* b = &a[0];
std::cout<< *(b +1); // this will print 2
That code is correct. The elements stored in a std::vector are guaranteed to be stored contiguously as of C++03.
This is the relevant part of the current standard C++ draft N3797 (23.3.6.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().
In whatever way a vector might be implemented, some things are guaranteed by the standard to remain consistent. A std::vector is always stored contiguously in memory and that is why it can work with random access iterators.

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.

is std::vector same as array[number]? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Are std::vector elements guaranteed to be contiguous?
does std::vector always contain the data in sequential memory addresses as array[number]?
For all types except bool, the standard requires the elements are contiguous in memory:
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()
Do keep in mind that std::vector<bool> has special requirements and is not the same as an array of bool.
Yes. Given:
std::vector<int> arr;
you can be sure that
&arr[0]
will give you a pointer to a contiguous array of ints that can (for instance) be passed legacy APIs.
Yes. It does not, however, allocate on the stack.
Yes, the vector use sequential memory for all the elements stored. That means random access is almost as fast as normal array's index.
But vector allocate its memory in heap instead of stack. So it could be less less efficient in some cases.
When you use the standard allocator, you can be sure that the allocated memory is continuous when using std::vector. In other words, foo[n+1] is the next element in the sequence after foo[n]. But std::vector is not an array, just like
int* blah = new int[100];
is not an array. But
int blah[100];
made on the stack is an array.
Pointers to allocated memory and arrays just happen to share semantics. They are not equal per the standard, so don't confuse the two.

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.