views:

108

answers:

4

Hi all,

If I create an object on the stack and push it into a list, then the object loses scope (outside of the for loop in the example below) will the object still exist in the list? If the list still holds the object, is that data now invalid/possibly corrupt?

Please let me know, and please explain the reasoning..

Thanks, jbu

class SomeObject{
public:
   AnotherObject x;
}

//And then...
void someMethod()
{
   std::list<SomeObject> my_list;
   for(int i = 0; i < SOME_NUMBER; i++)
   {
      SomeObject tmp;
      my_list.push_back(tmp);

      //after the for loop iteration, tmp loses scope
   }

   my_list.front(); //at this point will my_list be full of valid SomeObjects or will the SomeObjects no longer be valid, even if they still point to dirty data
}

EDIT: so what if it were a std::list<SomeObject*> my_list; instead of list...in that case would it be invalid?

+2  A: 

Yes, it's valid. push_back makes a copy.

quixoto
so what if it were a std::list my_list; instead of list...in that case would it be invalid?
jbu
@jbu - I'm not sure what you're asking here. It is a std::list. Perhaps a code example of what you mean?
Tim
std::list<SomeObject*> my_list; for() {SomeOjbect tmp; my_list.push_back( }
jbu
ah. No, that would be bad. In that case, your list is not a list of SomeObjects, but merely a list of pointers. Inside the for-loop, you create a SomeObject on the stack, and put a pointer into your list. Once you exit that scope, the SomeObject is gone, and your pointer is invalid.
Tim
+6  A: 

The standard containers make a copy of the object so the list is still ok in your example.

mkj
+4  A: 

All containers make a copy of what they store. It's a requirement that an object be copy-constructible and assignable, if it is to be used in a container.

So yes, vector, list, etc. all make a copy of your object.


An even shorter example:

struct foo {};
std::vector<foo> v;

v.push_back(foo()); 
// makes a copy of the temporary, which dies at the semicolon.

If it didn't make a copy, the above code would be bad.


The following code is not ok:

struct foo {};
std::vector<foo*> v;

{
    foo f;
    v.push_back(&f); // fine, but...
} // ...now f stops existing and...

v.front(); // ...points to a non-existent object.
GMan
A: 

With all STL containers (lists, vectors, maps, everything), the containers make a copy of what you add to the containers so, so long as what you add isn't a pointer or reference, you're safe.

If you write your own containers though, you have to be careful how you do things, since there's nothing stopping you from writing a type of container that stores references -- it would just be a nasty surprise to anyone that thought it worked like a standard container.

swestrup