std::vector: reserve required?

  • Thread starter Mike -- Email Ignored
  • Start date
M

Mike -- Email Ignored

In std::vector, is reserve or resize required?

On:
Linux mbrc32 2.6.22.1-41.fc7 #1 SMP Fri
Jul 27 18:10:34 EDT 2007 i686 athlon
i386 GNU/Linux
Using:
g++ (GCC) 4.1.2 20070502 (Red Hat 4.1.2-12)

The program below fails, but if the reserve(en)
is uncommented, it works. Is this as expected?

// vectst.cc 07/04/08

#include <iostream>
#include <vector>
using namespace std;

int main(int argc, const char* argv[])
{
int en = 10;
vector<int> vec;

// vec.reserve(en);
for (int jj = 0; jj < en; ++jj)
vec[jj] = jj;
for (int jj = 0; jj < en; ++jj)
cout << vec[jj] << endl;

exit (0);
}

Thanks,
Mike.
 
D

Darío Griffo

Mike said:
In std::vector, is reserve or resize required?

On:
Linux mbrc32 2.6.22.1-41.fc7 #1 SMP Fri
Jul 27 18:10:34 EDT 2007 i686 athlon
i386 GNU/Linux
Using:
g++ (GCC) 4.1.2 20070502 (Red Hat 4.1.2-12)

The program below fails, but if the reserve(en)
is uncommented, it works. Is this as expected?

// vectst.cc 07/04/08

#include <iostream>
#include <vector>
using namespace std;

int main(int argc, const char* argv[])
{
int en = 10;
vector<int> vec;

// vec.reserve(en);
for (int jj = 0; jj < en; ++jj)
vec[jj] = jj;
for (int jj = 0; jj < en; ++jj)
cout << vec[jj] << endl;

exit (0);
}

Thanks,
Mike.


No, you could do that (use reserve), or, use push_back()

int main(int argc, const char* argv[])
{
int en = 10;
vector<int> vec;

for (int jj = 0; jj < en; ++jj)
vec.push_back(jj);
for (int jj = 0; jj < en; ++jj)
cout << vec[jj] << endl;

return 0;
}
 
K

Kai-Uwe Bux

Mike said:
In std::vector, is reserve or resize required?

No, but you need to fill the vector somehow. You can do that either upon
construction, or by using push_back, insert, or resize.

The reserve() method, on the other hand does not grow the vector.
On:
Linux mbrc32 2.6.22.1-41.fc7 #1 SMP Fri
Jul 27 18:10:34 EDT 2007 i686 athlon
i386 GNU/Linux
Using:
g++ (GCC) 4.1.2 20070502 (Red Hat 4.1.2-12)

The program below fails, but if the reserve(en)
is uncommented, it works.

It does not. You are observing a manifestation of undefined behavior.
Is this as expected?

There are no expectations as to how undefined behavior will show itself.

From a quality of implementation point of view, would want to see an abort
if you compile the program with assertions turned on.

// vectst.cc 07/04/08

#include <iostream>
#include <vector>
using namespace std;

int main(int argc, const char* argv[])
{
int en = 10;
vector<int> vec;

// vec.reserve(en);
for (int jj = 0; jj < en; ++jj)
vec[jj] = jj;
for (int jj = 0; jj < en; ++jj)
cout << vec[jj] << endl;

Try something like

cout << vec.size() << endl;

and ponder the meaning of what you get.
exit (0);
}


Best

Kai-Uwe Bux
 
A

acehreli

Mike -- Email Ignored wrote:


In std::vector, is reserve or resize required?
On:
   Linux mbrc32 2.6.22.1-41.fc7 #1 SMP Fri
      Jul 27 18:10:34 EDT 2007 i686 athlon
      i386 GNU/Linux
Using:
   g++ (GCC) 4.1.2 20070502 (Red Hat 4.1.2-12)
The program below fails, but if the reserve(en)
is uncommented, it works.  Is this as expected?
// vectst.cc 07/04/08
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, const char* argv[])
{
   int                  en = 10;
   vector<int>          vec;
//   vec.reserve(en);
   for (int jj = 0; jj < en; ++jj)
      vec[jj] = jj;
   for (int jj = 0; jj < en; ++jj)
      cout << vec[jj] << endl;
   exit (0);
}
Thanks,
Mike.

No, you could do that (use reserve), or, use push_back()

reserve() does not make the vector larger. You must have meant "you
could use resize or push_back."

Ali
 
M

Mike -- Email Ignored


If the OP did not concentrate on the vec.reserve(en), the document you
show could be used to help with the problem. But because the OP does
expect some behavior from vec.reserve(en), the problem is not with
operator[].

Ali

Another test using:
vec.reserve(en);
for (int jj = 0; jj < en; ++jj)
vec[jj] = jj;
cout << "vec.size() = " << vec.size() << endl;

prevents the crash, but vec.size() returns zero, showing that
in this case, reserve() really does not work.

Mike.
 
L

LR

Mike said:
If the OP did not concentrate on the vec.reserve(en), the document you
show could be used to help with the problem. But because the OP does
expect some behavior from vec.reserve(en), the problem is not with
operator[].

Ali

Another test using:
vec.reserve(en);
for (int jj = 0; jj < en; ++jj)
vec[jj] = jj;
cout << "vec.size() = " << vec.size() << endl;

prevents the crash, but vec.size() returns zero,

What does vec.capacity() return?
showing that
in this case, reserve() really does not work.

I think it doesn't do what you expect. But why do you think it doesn't work?

Please consider this:
#include <iostream>
#include <vector>

int main() {
const unsigned int en = 10;
std::vector<int> v;
//
std::cout << "a " << v.size() << " " << v.capacity() << std::endl;
v.reserve(en);
std::cout << "b " << v.size() << " " << v.capacity() << std::endl;
//
for(unsigned int i=0; i<en; i++) {
v = i;
}
//
v.push_back(-8);
std::cout << "c " << v.size() << " " << v.capacity() << std::endl;
//
for(unsigned int i=0; i<en; i++) {
std::cout << "[" << i << "] " << v << std::endl;
}
}


Also, please consider this:
#include <iostream>
#include <vector>

int main() {
const unsigned int en = 10;
std::vector<int> v;
std::cout << "a " << v.size() << " " << v.capacity() << std::endl;
v.resize(en); // there's more than one way to do it
std::cout << "b " << v.size() << " " << v.capacity() << std::endl;
//
v[0] = -8;
v[9] = -7;
v.push_back(-9);
std::cout << "c " << v.size() << " " << v.capacity() << std::endl;
std::copy(v.begin(), v.end(), std::eek:stream_iterator<int>(std::cout,
" "));
}


LR
 
R

red floyd

Mike said:
If the OP did not concentrate on the vec.reserve(en), the document you
show could be used to help with the problem. But because the OP does
expect some behavior from vec.reserve(en), the problem is not with
operator[].

Ali

Another test using:
vec.reserve(en);
for (int jj = 0; jj < en; ++jj)
vec[jj] = jj;
cout << "vec.size() = " << vec.size() << endl;

prevents the crash, but vec.size() returns zero, showing that
in this case, reserve() really does not work.

No, reserve() does work. You misunderstand how it does.
vector<>::reserve changes the CAPACITY -- that is, you can use
push_back() or resize() up to the amount you've reserved without
the vector reallocating. It does not change the SIZE of the vector.

Try this:

#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

int main()
{
vector<int> v;

cout << "size = " << v.size() << "\n"
<< "capacity = " << v.capacity << "\n";

v.reserve(200);

cout << "size = " << v.size() << "\n"
<< "capacity = " << v.capacity << "\n";

v.resize(200);

cout << "size = " << v.size() << "\n"
<< "capacity = " << v.capacity << endl;

return 0;
}
 
R

red floyd

red said:
Mike said:
On Jul 4, 7:54 am, (e-mail address removed) wrote:
http://www.cplusplus.com/reference/stl/vector/operator[].html
If the OP did not concentrate on the vec.reserve(en), the document you
show could be used to help with the problem. But because the OP does
expect some behavior from vec.reserve(en), the problem is not with
operator[].

Ali

Another test using:
vec.reserve(en);
for (int jj = 0; jj < en; ++jj)
vec[jj] = jj;
cout << "vec.size() = " << vec.size() << endl;

prevents the crash, but vec.size() returns zero, showing that
in this case, reserve() really does not work.

No, reserve() does work. You misunderstand how it does.
vector<>::reserve changes the CAPACITY -- that is, you can use
push_back() or resize() up to the amount you've reserved without
the vector reallocating. It does not change the SIZE of the vector.

Try this:

#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

int main()
{
vector<int> v;

cout << "size = " << v.size() << "\n"
<< "capacity = " << v.capacity << "\n";

v.reserve(200);

cout << "size = " << v.size() << "\n"
<< "capacity = " << v.capacity << "\n";

v.resize(200);

cout << "size = " << v.size() << "\n"
<< "capacity = " << v.capacity << endl;

return 0;
}

Crap. Typo. All those v.capacity calls should be v.capacity()
 
J

James Kanze

Mike -- Email Ignored wrote:

I get a core dump from g++ 4.2.1, when I compile with the usual
options. With or without the reserve() commented out. You
probably forgot the necessary options to make g++ usable. (One
of these days, someone will come out with a compiler which is
usable without special options. But it's not happened yet.)
It does not. You are observing a manifestation of undefined
behavior.
There are no expectations as to how undefined behavior will
show itself.

Yes and no. From experience, I find that undefined behavior
usually works in all of your tests, and then fails in the most
embarassing way possible in the demo before the most important
client.
From a quality of implementation point of view, would want to
see an abort if you compile the program with assertions turned
on.

You do with g++. I'm pretty sure you also do with VC++, but I
don't have a Windows machine handy here to test it with.
 
M

Mike -- Email Ignored

I get a core dump from g++ 4.2.1, when I compile with the usual options.
With or without the reserve() commented out. You probably forgot the
necessary options to make g++ usable. (One of these days, someone will
come out with a compiler which is usable without special options. But
it's not happened yet.)

You may have forgotten some option if you get a failure with reserve()
uncommented; in my case options are correct as verified by extensive
use in other contexts.
Yes and no. From experience, I find that undefined behavior usually
works in all of your tests, and then fails in the most embarassing way
possible in the demo before the most important client.
I guess I should have said I was referring to the standard as is
usually the case on this group. There is no "Yes and no".
You do with g++. I'm pretty sure you also do with VC++, but I don't
have a Windows machine handy here to test it with.

I see that in you use vec.at(jj) instead of vec[jj], it throws
an exception if the index is out of range. I changed the code to use
vec.at(jj) where there is uncertainly. My problem is solved.

Mike.
 
M

Mike -- Email Ignored

You may have forgotten some option if you get a failure with reserve()
uncommented; in my case options are correct as verified by extensive use
in other contexts.
Correction. You may have no option error. As indicated elsewhere
in this thread, reserve() is never correct in the original code
presented. Hopefully, if you use resize() instead, the code will work.

[...]

Mike.
 
J

James Kanze

You may have forgotten some option if you get a failure with
reserve() uncommented; in my case options are correct as
verified by extensive use in other contexts.

I used the usual options that I use for compiling production
code:
-std=c++98
-ffor-scope
-fno-gnu-keywords
-foperator-names
-pipe
-Wall
-W
-Wno-sign-compare
-Wno-deprecated
-Wno-non-virtual-dtor
-Wpointer-arith
-Wno-unused
-Wno-switch
-Wno-missing-field-initializers
-ggdb3
-D_GLIBCXX_CONCEPT_CHECKS
-D_GLIBCXX_DEBUG
-D_GLIBCXX_DEBUG_PEDANTIC
They're not complete (I forget why we don't have -pedantic in
there), but they're a start.

The important ones for error checking in the library are the
last three. Logically, they should be the default, but hey, no
compiler I know gets the defaults right.
I guess I should have said I was referring to the standard as is
usually the case on this group. There is no "Yes and no".

I guess I should have explained in detail that this was meant as
a somewhat humorous characterization. It didn't occur to me
that anyone would miss this.
I see that in you use vec.at(jj) instead of vec[jj], it throws
an exception if the index is out of range. I changed the code
to use vec.at(jj) where there is uncertainly. My problem is
solved.

Except that you want an abort, not an exception. (The problem
isn't cases where there is uncertainly. Uncertainty can be
removed by means of an if. The problem is where your certitudes
turn out to be wrong.)
 
J

James Kanze

Correction. You may have no option error. As indicated elsewhere
in this thread, reserve() is never correct in the original code
presented. Hopefully, if you use resize() instead, the code will work.

Obviously, because it's then correct. (There are doubtlessly
some bugs still floating around somewhere in the GNU library,
but nothing that obvious.)
 
M

Mike -- Email Ignored

On Jul 4, 10:25 pm, Mike -- Email Ignored <[email protected]>
wrote:
[...]

I used the usual options that I use for compiling production code:
-std=c++98
-ffor-scope
-fno-gnu-keywords
-foperator-names
-pipe
-Wall
-W
-Wno-sign-compare
-Wno-deprecated
-Wno-non-virtual-dtor
-Wpointer-arith
-Wno-unused
-Wno-switch
-Wno-missing-field-initializers
-ggdb3
-D_GLIBCXX_CONCEPT_CHECKS
-D_GLIBCXX_DEBUG
-D_GLIBCXX_DEBUG_PEDANTIC
They're not complete (I forget why we don't have -pedantic in there),
but they're a start.

You use many more options than I do. Are all these really necessary?

[...]
Except that you want an abort, not an exception. (The problem isn't
cases where there is uncertainly. Uncertainty can be removed by means
of an if. The problem is where your certitudes turn out to be wrong.)

Why an abort rather than an exception? I would think that it
depend on the application.

For certitude, consider things like:

std::vector<int> vec;
...
for (int jj = 0; jj < vec.size(); ++jj)
cout << vec[jj] << endl;

I first went through the code and changed all [] to at. Then I
looked back and saw things like the above fragment, and decided
I was being ridiculous, and throwing away cycles for nothing.

Mike.
 
J

Jerry Coffin

[ ... ]
For certitude, consider things like:

std::vector<int> vec;
...
for (int jj = 0; jj < vec.size(); ++jj)
cout << vec[jj] << endl;

I first went through the code and changed all [] to at. Then I
looked back and saw things like the above fragment, and decided
I was being ridiculous, and throwing away cycles for nothing.

Better still, replace the whole loop with:

std::copy(vec.begin(), vec.end(),
std::eek:stream_iterator<int>(std::cout, "\n"));
 
J

Jim Langston

Mike -- Email Ignored said:
In std::vector, is reserve or resize required?

On:
Linux mbrc32 2.6.22.1-41.fc7 #1 SMP Fri
Jul 27 18:10:34 EDT 2007 i686 athlon
i386 GNU/Linux
Using:
g++ (GCC) 4.1.2 20070502 (Red Hat 4.1.2-12)

The program below fails, but if the reserve(en)
is uncommented, it works. Is this as expected?

No. It is unspecified behavior either way. reserve will allocate memory to
extend the size of an array, but it does not actually grow the size.
resize() will both allocate the memory and extend the size also.

Note, that changing vec[jj] = jj;
to vec.push_back( jj );
would mean you don't need resize or reserve. However, if you know before
hand how much memory you are going to need, how many elements, you may wish
to resize it to avoid needless calls to new.

int en = 10;
vec<int> vec;

vec.reserve( en ); // Allocates memory, doesn't change size
for (int jj = 0; jj < en; ++jj)
vec.push_back( jj );

alternately:
vec.resize( en ); // Allocates memory and changes size
for (int jj = 0; jj < en; ++jj)
vec[jj] = jj;

// vectst.cc 07/04/08

#include <iostream>
#include <vector>
using namespace std;

int main(int argc, const char* argv[])
{
int en = 10;
vector<int> vec;

// vec.reserve(en);
for (int jj = 0; jj < en; ++jj)
vec[jj] = jj;
for (int jj = 0; jj < en; ++jj)
cout << vec[jj] << endl;

exit (0);
}
 
J

James Kanze

On Jul 4, 10:25 pm, Mike -- Email Ignored <[email protected]>
wrote:
[...]
I used the usual options that I use for compiling production code:
-std=c++98
-ffor-scope
-fno-gnu-keywords
-foperator-names
-pipe
-Wall
-W
-Wno-sign-compare
-Wno-deprecated
-Wno-non-virtual-dtor
-Wpointer-arith
-Wno-unused
-Wno-switch
-Wno-missing-field-initializers
-ggdb3
-D_GLIBCXX_CONCEPT_CHECKS
-D_GLIBCXX_DEBUG
-D_GLIBCXX_DEBUG_PEDANTIC
They're not complete (I forget why we don't have -pedantic in there),
but they're a start.
You use many more options than I do. Are all these really necessary?

They were at one time, in the context I was working. Options
are a lot like includes: you add them when you need them, but
they don't get removed if the cease to be necessary:). Also,
-pedantic is generally recommended, but I don't have it. I do
remember having it once, but I forget why I removed it. (I
think it was because -pedantic turned off support for long long,
which I need, even if it isn't currently part of C++. But I
also seem to recall having seen recently that there is a
separate option which can be used to control this, overriding
-pedantic.)

Typically, however, I'd say that that list is about average for
what you need with just about any compiler.
[...]
Except that you want an abort, not an exception. (The
problem isn't cases where there is uncertainly. Uncertainty
can be removed by means of an if. The problem is where your
certitudes turn out to be wrong.)
Why an abort rather than an exception? I would think that it
depend on the application.

It's a programming error. Something which can't happen, but
did. In such cases, you can no longer make any assumptions
concerning the state of the program, and the best thing you can
do is to terminate as quickly as possible, executing as little
code as possible.

And yes, it does depend on the application. That's a more or
less general rule, which leans toward safety and robustness; in
some cases, however, if an error goes unnoticed, it's not an
error, and whether it's noticed immediately or an undeterminate
moment downstream doesn't matter. (A typical case might be
games programming.)
For certitude, consider things like:

std::vector<int> vec;
...
for (int jj = 0; jj < vec.size(); ++jj)
cout << vec[jj] << endl;
I first went through the code and changed all [] to at. Then
I looked back and saw things like the above fragment, and
decided I was being ridiculous, and throwing away cycles for
nothing.

What cycles are you throwing away. In one case, the library
code verifies the index, and then aborts, and in the other, it
verifies the index, and then raises an exception. In a well
written library, with normal options, you execute the if, and
nothing else, in either version. (And of course, a good
compiler can, and probably should, recognize that the if can
never fail, and suppress it.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top