There is a thread in the comments section in this post about using std::vector::reserve() vs. std::vector::resize().
Here is the original code:
void MyClass::my_method()
{
my_member.reserve(n_dim);
for(int k = 0 ; k < n_dim ; k++ )
my_member[k] = k ;
}
I believe that to write elements in the vector, the correct thing to do is to call std::vector::resize(), not std::vector::reserve().
In fact, the following test code "crashes" in debug builds in VS2010 SP1:
#include <vector>
using namespace std;
int main()
{
vector<int> v;
v.reserve(10);
v[5] = 2;
return 0;
}
Am I right, or am I wrong? And is VS2010 SP1 right, or is it wrong?
There are two different methods for a reason:
std::vector::reserve will allocate the memory but will not resize your vector, which will have a logical size the same as it was before.
std::vector::resize will actually modify the size of your vector and will fill any space with objects in their default state. If they are ints, they will all be zero.
After reserve, in your case, you will need a lot of push_backs to write to element 5.
If you don't wish to do that then in your case you should use resize.
One thing about reserve: if you then add elements with push_back, until you reach the capacity you have reserved, any existing references, iterators or pointers to data in your vector will remain valid. So if I reserve 1000 and my size is 5, the &vec[4] will remain the same until the vector has 1000 elements. After that, I can call push_back() and it will work, but the stored pointer of &vec[4] earlier may no longer be valid.
It depends on what you want to do. reserve does not add any
elements to the vector; it only changes the capacity(), which
guarantees that adding elements will not reallocate (and e.g.
invalidate iterators). resize adds elements immediately. If you want
to add elements later (insert(), push_back()), use reserve. If you
want to access elements later (using [] or at()), use resize. So
youre MyClass::my_method can be either:
void MyClass::my_method()
{
my_member.clear();
my_member.reserve( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member.push_back( k );
}
}
or
void MyClass::my_method()
{
my_member.resize( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member[k] = k;
}
}
Which one you chose is a question of taste, but the code you quote is
clearly incorrect.
There probably should be a discussion about when both methods are called with a number that's LESS than the current size of the vector.
Calling reserve() with a number smaller than the capacity will not affect the size or the capacity.
Calling resize() with a number smaller than current size the container will be reduced to that size effectively destroying the excess elements.
To sum up resize() will free up memory whereas reserve() will not.
Yes you’re correct, Luchian just made a typo and is probably too coffee-deprived to realise his mistake.
resize actually changes the amount of elements in the vector, new items are default constructed if the resize causes the vector to grow.
vector<int> v;
v.resize(10);
auto size = v.size();
in this case size is 10.
reserve on the other hand only requests that the internal buffer be grown to the specified size but does not change the "size" of the array, only its buffer size is changed.
vector<int> v;
v.reserve(10);
auto size = v.size();
in this case size is still 0.
So to answer your question, yes you are right, even if you reserve enough space you are still accessing uninitialized memory with the index operator. With an int thats not so bad but in the case of a vector of classes you would be accessing objects which have not been constructed.
Bounds checking of compilers set to debug mode can obviously be confused by this behavior which may be why you are experiencing the crash.
Related
There is a thread in the comments section in this post about using std::vector::reserve() vs. std::vector::resize().
Here is the original code:
void MyClass::my_method()
{
my_member.reserve(n_dim);
for(int k = 0 ; k < n_dim ; k++ )
my_member[k] = k ;
}
I believe that to write elements in the vector, the correct thing to do is to call std::vector::resize(), not std::vector::reserve().
In fact, the following test code "crashes" in debug builds in VS2010 SP1:
#include <vector>
using namespace std;
int main()
{
vector<int> v;
v.reserve(10);
v[5] = 2;
return 0;
}
Am I right, or am I wrong? And is VS2010 SP1 right, or is it wrong?
There are two different methods for a reason:
std::vector::reserve will allocate the memory but will not resize your vector, which will have a logical size the same as it was before.
std::vector::resize will actually modify the size of your vector and will fill any space with objects in their default state. If they are ints, they will all be zero.
After reserve, in your case, you will need a lot of push_backs to write to element 5.
If you don't wish to do that then in your case you should use resize.
One thing about reserve: if you then add elements with push_back, until you reach the capacity you have reserved, any existing references, iterators or pointers to data in your vector will remain valid. So if I reserve 1000 and my size is 5, the &vec[4] will remain the same until the vector has 1000 elements. After that, I can call push_back() and it will work, but the stored pointer of &vec[4] earlier may no longer be valid.
It depends on what you want to do. reserve does not add any
elements to the vector; it only changes the capacity(), which
guarantees that adding elements will not reallocate (and e.g.
invalidate iterators). resize adds elements immediately. If you want
to add elements later (insert(), push_back()), use reserve. If you
want to access elements later (using [] or at()), use resize. So
youre MyClass::my_method can be either:
void MyClass::my_method()
{
my_member.clear();
my_member.reserve( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member.push_back( k );
}
}
or
void MyClass::my_method()
{
my_member.resize( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member[k] = k;
}
}
Which one you chose is a question of taste, but the code you quote is
clearly incorrect.
There probably should be a discussion about when both methods are called with a number that's LESS than the current size of the vector.
Calling reserve() with a number smaller than the capacity will not affect the size or the capacity.
Calling resize() with a number smaller than current size the container will be reduced to that size effectively destroying the excess elements.
To sum up resize() will free up memory whereas reserve() will not.
Yes you’re correct, Luchian just made a typo and is probably too coffee-deprived to realise his mistake.
resize actually changes the amount of elements in the vector, new items are default constructed if the resize causes the vector to grow.
vector<int> v;
v.resize(10);
auto size = v.size();
in this case size is 10.
reserve on the other hand only requests that the internal buffer be grown to the specified size but does not change the "size" of the array, only its buffer size is changed.
vector<int> v;
v.reserve(10);
auto size = v.size();
in this case size is still 0.
So to answer your question, yes you are right, even if you reserve enough space you are still accessing uninitialized memory with the index operator. With an int thats not so bad but in the case of a vector of classes you would be accessing objects which have not been constructed.
Bounds checking of compilers set to debug mode can obviously be confused by this behavior which may be why you are experiencing the crash.
There is a thread in the comments section in this post about using std::vector::reserve() vs. std::vector::resize().
Here is the original code:
void MyClass::my_method()
{
my_member.reserve(n_dim);
for(int k = 0 ; k < n_dim ; k++ )
my_member[k] = k ;
}
I believe that to write elements in the vector, the correct thing to do is to call std::vector::resize(), not std::vector::reserve().
In fact, the following test code "crashes" in debug builds in VS2010 SP1:
#include <vector>
using namespace std;
int main()
{
vector<int> v;
v.reserve(10);
v[5] = 2;
return 0;
}
Am I right, or am I wrong? And is VS2010 SP1 right, or is it wrong?
There are two different methods for a reason:
std::vector::reserve will allocate the memory but will not resize your vector, which will have a logical size the same as it was before.
std::vector::resize will actually modify the size of your vector and will fill any space with objects in their default state. If they are ints, they will all be zero.
After reserve, in your case, you will need a lot of push_backs to write to element 5.
If you don't wish to do that then in your case you should use resize.
One thing about reserve: if you then add elements with push_back, until you reach the capacity you have reserved, any existing references, iterators or pointers to data in your vector will remain valid. So if I reserve 1000 and my size is 5, the &vec[4] will remain the same until the vector has 1000 elements. After that, I can call push_back() and it will work, but the stored pointer of &vec[4] earlier may no longer be valid.
It depends on what you want to do. reserve does not add any
elements to the vector; it only changes the capacity(), which
guarantees that adding elements will not reallocate (and e.g.
invalidate iterators). resize adds elements immediately. If you want
to add elements later (insert(), push_back()), use reserve. If you
want to access elements later (using [] or at()), use resize. So
youre MyClass::my_method can be either:
void MyClass::my_method()
{
my_member.clear();
my_member.reserve( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member.push_back( k );
}
}
or
void MyClass::my_method()
{
my_member.resize( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member[k] = k;
}
}
Which one you chose is a question of taste, but the code you quote is
clearly incorrect.
There probably should be a discussion about when both methods are called with a number that's LESS than the current size of the vector.
Calling reserve() with a number smaller than the capacity will not affect the size or the capacity.
Calling resize() with a number smaller than current size the container will be reduced to that size effectively destroying the excess elements.
To sum up resize() will free up memory whereas reserve() will not.
Yes you’re correct, Luchian just made a typo and is probably too coffee-deprived to realise his mistake.
resize actually changes the amount of elements in the vector, new items are default constructed if the resize causes the vector to grow.
vector<int> v;
v.resize(10);
auto size = v.size();
in this case size is 10.
reserve on the other hand only requests that the internal buffer be grown to the specified size but does not change the "size" of the array, only its buffer size is changed.
vector<int> v;
v.reserve(10);
auto size = v.size();
in this case size is still 0.
So to answer your question, yes you are right, even if you reserve enough space you are still accessing uninitialized memory with the index operator. With an int thats not so bad but in the case of a vector of classes you would be accessing objects which have not been constructed.
Bounds checking of compilers set to debug mode can obviously be confused by this behavior which may be why you are experiencing the crash.
There is a thread in the comments section in this post about using std::vector::reserve() vs. std::vector::resize().
Here is the original code:
void MyClass::my_method()
{
my_member.reserve(n_dim);
for(int k = 0 ; k < n_dim ; k++ )
my_member[k] = k ;
}
I believe that to write elements in the vector, the correct thing to do is to call std::vector::resize(), not std::vector::reserve().
In fact, the following test code "crashes" in debug builds in VS2010 SP1:
#include <vector>
using namespace std;
int main()
{
vector<int> v;
v.reserve(10);
v[5] = 2;
return 0;
}
Am I right, or am I wrong? And is VS2010 SP1 right, or is it wrong?
There are two different methods for a reason:
std::vector::reserve will allocate the memory but will not resize your vector, which will have a logical size the same as it was before.
std::vector::resize will actually modify the size of your vector and will fill any space with objects in their default state. If they are ints, they will all be zero.
After reserve, in your case, you will need a lot of push_backs to write to element 5.
If you don't wish to do that then in your case you should use resize.
One thing about reserve: if you then add elements with push_back, until you reach the capacity you have reserved, any existing references, iterators or pointers to data in your vector will remain valid. So if I reserve 1000 and my size is 5, the &vec[4] will remain the same until the vector has 1000 elements. After that, I can call push_back() and it will work, but the stored pointer of &vec[4] earlier may no longer be valid.
It depends on what you want to do. reserve does not add any
elements to the vector; it only changes the capacity(), which
guarantees that adding elements will not reallocate (and e.g.
invalidate iterators). resize adds elements immediately. If you want
to add elements later (insert(), push_back()), use reserve. If you
want to access elements later (using [] or at()), use resize. So
youre MyClass::my_method can be either:
void MyClass::my_method()
{
my_member.clear();
my_member.reserve( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member.push_back( k );
}
}
or
void MyClass::my_method()
{
my_member.resize( n_dim );
for ( int k = 0; k < n_dim; ++ k ) {
my_member[k] = k;
}
}
Which one you chose is a question of taste, but the code you quote is
clearly incorrect.
There probably should be a discussion about when both methods are called with a number that's LESS than the current size of the vector.
Calling reserve() with a number smaller than the capacity will not affect the size or the capacity.
Calling resize() with a number smaller than current size the container will be reduced to that size effectively destroying the excess elements.
To sum up resize() will free up memory whereas reserve() will not.
Yes you’re correct, Luchian just made a typo and is probably too coffee-deprived to realise his mistake.
resize actually changes the amount of elements in the vector, new items are default constructed if the resize causes the vector to grow.
vector<int> v;
v.resize(10);
auto size = v.size();
in this case size is 10.
reserve on the other hand only requests that the internal buffer be grown to the specified size but does not change the "size" of the array, only its buffer size is changed.
vector<int> v;
v.reserve(10);
auto size = v.size();
in this case size is still 0.
So to answer your question, yes you are right, even if you reserve enough space you are still accessing uninitialized memory with the index operator. With an int thats not so bad but in the case of a vector of classes you would be accessing objects which have not been constructed.
Bounds checking of compilers set to debug mode can obviously be confused by this behavior which may be why you are experiencing the crash.
When I call std::vector::reserve when the identifier is of type std::vector<Foo*> reserve(...) does nothing:
std::vector<int*> bar;
bar.reserve(20);
//I expect bar.size to return 20...
std::size_t sz = bar.size();
for(std::size_t i = 0; i < sz; ++i) {
//Do Stuff to all items!
}
The aforementioned for loop runs exactly zero times and bar.size() returns zero. I do not remember if this is also true for all other STL containers, but if so, including the behavior for std::vector: WHY?
.reserve() doesn't change the size of a vector. The member function you are looking for is .resize(). reserve() is simply an optimization. If you are going to add a bunch of things to a vector one-by-one using push_back() then telling it how many you will add using reserve() can make the code run a little bit faster. But just calling reserve() doesn't change the size.
vector::reserve() changes the capacity of a vector, not its size.
capacity is how much memory has been allocated internally to hold elements of the vector. size is how many elements have actually held by the vector. vector::resize() affects the latter.
reserve changes the capacity of the vector, not the size. You probably want resize
The resize() function makes vector contain the required number of elements. If we require less elements than vector already contain, the last ones will be deleted. If we ask vector to grow, it will enlarge its size and fill the newly created elements with zeroes.
vector<int> v(20);
for(int i = 0; i < 20; i++) {
v[i] = i+1;
}
v.resize(25);
for(int i = 20; i < 25; i++) {
v[i] = i*2;
}
But if we use push_back() after resize(), it will add elements AFTER the newly allocated size, but not INTO it. In the example above the size of the resulting vector is 25, while if we use push_back() in a second loop, it would be 30.
vector<int> v(20);
for(int i = 0; i < 20; i++) {
v[i] = i+1;
}
v.resize(25);
for(int i = 20; i < 25; i++) {
v.push_back(i*2); // Writes to elements with indices [25..30), not [20..25) ! <
}
Then where is the advantage of resize() function ? Doesn't it creates a confusion for indexing and accessing elements from the vector ?
It sounds as though you should be using vector::reserve.
vector::resize is used to initialize the newly created space with a given value (or just the default.) The second parameter to the function is the initialization value to use.
Remember the alternative - reserve. resize is used when you want to act on the vector using the [] operator -- hence you need a "empty" table of elements. resize is not intended to be used with push_back. Use reserve if you want to prepare the array for push_back.
Resize is mainly usefull if the array has meaningful "empty" constructor, when you can create an array of empty elements, and only change the ones that are meaningful.
The resize() method changes the vector's size, which is not the same as the vector's capacity.
It is very important to understand the distinction between these two values:
The size is the number of actual elements that the vector contains.
The capacity is the maximum number of elements that the vector could contain without reallocating a larger chunk of memory.
A vector's capacity is always larger or equal to its size. A vector's capacity never shrinks, even when you reduce its size, with one exception: when you use swap() to exchange the contents with another vector. And as others have mentioned, you can increase a vector's capacity by calling reserve().
I think that using the correct terminology for size and capacity makes it easier to understand the C++ vector class and to speak clearly about its behavior.
resize() function changes the actual content of the vector by inserting or erasing elements from the vector. It does not only change its storage capacity. To direct a change only in storage capacity, use vector::reserve instead. Have a look at the vector visualization in the link, notice where v.back is pointing to.
I don't really understand the confusion. The advantage of resize is that it resizes your vector. Having to do a loop of push_backs is both tedious and may require more than one "actual" resize.
If you want to "resize" your vector without changing its accessible indexes then use std::vector<T>::reserve. That will change the size of the internal allocated array without actually "adding" anything.