Re: Am I misusing std::vector?
loose AT astron DOT nl wrote:
Hi,
I was surprised by the output of the program below. From what I
understand from the C++ STL documentation, vector<T>::resize(N), will
create N *newly constructed* objects of T. So, I expected *v[0].ip to
be equal to 0, and *v[sz-1].ip equal to -77. However, I discovered,
using a few different compilers (two different versions of gcc, and
icc), that both return -77. It turns out that only *one* object is
being constructed and this one object seems to be bitwise copied to the
other members. See my code below and try it for yourself.
Am I missing something here?
Regards,
Marcel Loose.
<code>
#include <vector>
#include <iostream>
using namespace std;
struct A
{
A(int i = 0) { ip = new int(i); }
~A() { delete ip; }
int* ip;
};
int main()
{
const unsigned sz = 1000000;
vector<A> v;
v.resize(sz);
*v[sz-1].ip = -77;
cout << "v.size() = " << v.size() << endl;
cout << "v[0].ip = " << v[0].ip << "; " << "*v[0].ip = " <<
*v[0].ip << endl;
cout << "v[sz-1].ip = " << v[sz-1].ip << "; " << "*v[sz-1].ip = "
<< *v[sz-1].ip << endl;
return 0;
}
</code>
resize is equivalent to inserting n copies of the second argument, which
defaults to the default constructor. So, your default constructor
executes once, creating a single new int. The address of that one int*
is then copied via the default copy constructor to all the copies,
resulting in all of them pointing to the same object.
You want a deep copy when resize duplicates elements, so you want to
allocate a new pointer. Add the following line:
A(const A& b) : ip(new int(*b.ip)) { }
to your class. Everything now works.
--
Ron House house@usq.edu.au
http://www.sci.usq.edu.au/staff/house
Ethics website: http://www.sci.usq.edu.au/staff/house/goodness
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]