Vector and adding of object

G

gamehack

Hi all,

Let me first start off with this piece of code:

for(int i = 0; i < NumBoxes; ++i)
{
Box b(i, start, money[15], false);

this->boxes.push_back(b);

start++;
}

Here a Box object is created on the stack as soon as the for loop is
entered. My question: Is it true that a copy of the object is pushed
onto the vector? And after the loop ends, the object b is destroyed.
What I'm concerned about is that if NumBoxes is big, there would be a
lot of overhead just creating and destroying the same object. Is it
possible to allocate one object dynamically and just reuse it? I can do
something like:
Box* b = new Box(i, start, money[15], false);
But then what would be my argument for push_back? Would it be
this->boxes.push_back(*b); ?

Thanks a lot
 
V

Victor Bazarov

gamehack said:
Let me first start off with this piece of code:

for(int i = 0; i < NumBoxes; ++i)
{
Box b(i, start, money[15], false);

this->boxes.push_back(b);

start++;
}

Here a Box object is created on the stack as soon as the for loop is
entered. My question: Is it true that a copy of the object is pushed
onto the vector?
Yes.

> And after the loop ends, the object b is destroyed.

'b' is "destroyed" after the end of _each_ iteration.
What I'm concerned about is that if NumBoxes is big, there would be a
lot of overhead just creating and destroying the same object.

Can be.
> Is it
possible to allocate one object dynamically and just reuse it? I can do
something like:
Box* b = new Box(i, start, money[15], false);
But then what would be my argument for push_back? Would it be
this->boxes.push_back(*b); ?

Whatever the actual solution is, you need to always begin with deciding
whether it is necessary to make your program less readable for the sake
of making it faster, and by how much. Without actual tests it is not
possible to make this call. Now, the simplest solution I can see is

for (int i = 0; i < NumBoxes; ++i, ++start)
this->boxes.push_back(Box(i, start, money[15], false);

which is clear, short, easy for the compiler to optimise, etc. If you
can also do

this->boxes.reserve(this->boxes.size() + NumBoxes);

just _before_ the loop, it's going to help as well.

Now, stop worrying about any overhead, make your program *work* _first_,
and only then think about making it fast. And when you are trying to
improve your program's performance, don't guess -- measure!

V
 
M

Marcus Kwok

gamehack said:
Hi all,

Let me first start off with this piece of code:

for(int i = 0; i < NumBoxes; ++i)
{
Box b(i, start, money[15], false);

this->boxes.push_back(b);

start++;
}

Here a Box object is created on the stack as soon as the for loop is
entered. My question: Is it true that a copy of the object is pushed
onto the vector? And after the loop ends, the object b is destroyed.
What I'm concerned about is that if NumBoxes is big, there would be a
lot of overhead just creating and destroying the same object. Is it
possible to allocate one object dynamically and just reuse it? I can do
something like:
Box* b = new Box(i, start, money[15], false);
But then what would be my argument for push_back? Would it be
this->boxes.push_back(*b); ?

Well, you could just push it onto the vector as soon as you create it:

for (int i = 0; i < NumBoxes; ++i) {
boxes.push_back(Box(i, start, money[15], false));
++start;
}
 
T

Thomas Tutone

gamehack said:
Hi all,

Let me first start off with this piece of code:

for(int i = 0; i < NumBoxes; ++i)
{
Box b(i, start, money[15], false);

this->boxes.push_back(b);

start++;
}

I'm curious about something unrelated to your question. Why do you
say:

this->boxes.push_back(b);

and not just:

boxes.push_back(b);

? Is this part of some complicated class template that requires it?
If not, including "this" seems odd (and potentially confusing).

Just curious.

Best regards,

Tom
 
B

benben

I'm curious about something unrelated to your question. Why do you
say:

this->boxes.push_back(b);

and not just:

boxes.push_back(b);

? Is this part of some complicated class template that requires it?
If not, including "this" seems odd (and potentially confusing).

It could be a class template. Even not, sometimes I am tempted to use
this-> just to bring up the auto-complete list :)
Just curious.

Best regards,

Tom

Ben
 
D

Daniel T.

"gamehack said:
Hi all,

Let me first start off with this piece of code:

for(int i = 0; i < NumBoxes; ++i)
{
Box b(i, start, money[15], false);

this->boxes.push_back(b);

start++;
}

Here a Box object is created on the stack as soon as the for loop is
entered. My question: Is it true that a copy of the object is pushed
onto the vector? And after the loop ends, the object b is destroyed.

That depends on how aggressively the compiler is optimizing the code I
would think.
What I'm concerned about is that if NumBoxes is big, there would be a
lot of overhead just creating and destroying the same object.

Your concern is misplaced, unless you have actually measured the
performance of your code and found this to be a bottleneck.
Is it
possible to allocate one object dynamically and just reuse it? I can do
something like:
Box* b = new Box(i, start, money[15], false);
But then what would be my argument for push_back? Would it be
this->boxes.push_back(*b); ?

The above doesn't help because you are still creating and then
destroying a Box (I hope you have a delete in there somewhere,) only now
you are putting it in the heap instead of the stack (which may be
slower.)

If I had that code and it showed to actually be too slow, then I would
first do as others have suggested and make a temporary. That may help
the compiler optimize it better. If that didn't work then I would do
something like:

Box b(money[15], false);
for ( int i = 0; i < NumBoxes; ++i ) {
b.setI(i);
b.setStart(start++);
boxes.push_back(b);
}

That way, the code is using the same box over and over (with suitable
changes) rather than making a new one every time.
 
L

Lyell Haynes

If you find that this code is slow for some reason, you should consider
either storing bald pointers in the vector (i.e. std::vector<Box *>) or
using a smart pointer like boost::shared_ptr (don't use std::auto_ptr
in a vector).

With this method, your code may look like this:

typedef std::vector<Box *> BoxPointerVec;
BoxPointerVec boxPointerVec;
....
for (int i=0; i < NumBoxes; ++i)
{
Box *b = new Box(i, start, money[15], false);
boxPointerVec.push_back(b);
}

However, the issue with this code is that whenever you remove a box
pointer from the vector, you'll need to delete it after you're finished
using it. You'll also need to iterate through all the remaining
pointers in the vector and delete them as well before destroying the
vector.

i.e.

BoxPointerVec::iterator it, end = boxPointerVec.end();
for (it = boxPointerVec.begin(); it != end; ++it)
{
delete *it;
}

The way to get around this is to use something like boost:shared_ptr,
which will handle deleting the pointer itself, and because it is a
reference counted pointer, it is "copy-safe" and therefore usable in
containers.

So, the code above would be changed to:

typedef std::vector<boost::shared_ptr<Box> > BoxPointerVector
BoxVector boxPointerVector;
....
for (int i=0; i < NumBoxes; ++i)
{
boost::shared_ptr<Box> b(new Box(i, start, money[15], false));
boxPointerVec.push_back(b);
}


All done!
 

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

No members online now.

Forum statistics

Threads
473,787
Messages
2,569,629
Members
45,332
Latest member
LeesaButts

Latest Threads

Top