std::list how to store copy of an object?

Hello, I'm currently trying to figure out how to store the copy of an object in a std::list so the data of the list entry remains untouched when the object I was getting the data from is getting destroyed.

Now I know I can simply add an entry in a std::list with push_front()/push_back() but I can't seem to find any clear statement if the object that gets added to the list is a copy or just a pointer of/to the original object.

I already tried to test some stuff with sample code but I'm not sure what to make out of it. Maybe someone can explain to me what is happening in the following sample code:
1
2
3
4
5
6
7
8
9
10
11
12
13
std::list<Object*> pointer_list;
std::list<Object> object_list;

Object* test = new Object(/*the constructor gets called with some parameters here*/);

// here some funtions of test are called and its data members are being modified

pointer_list.push_back(test);
object_list.push_back(*test);

delete test;
// after this line is called, the data members of test are being "deleted" as well as the data in the according list entry in pointer_list
// however in object_list the entry seems to remain untouched, does that mean the object was actually being copied in it? 

Since the data in object_list was not "deleted" I dare to ask: Is this the way to do what I wanted to do? Or is there some other, "proper" way to do this?
Last edited on
It is a copy. The copy constructor is called. To do it how you want to, you should not delete the pointer and keep reference of how many time it is used (Reference counting).
Last edited on
Well in practice I don't delete the pointer manually, I just want to be sure that the data stays untouched in the list after it was being put in it.

Would it be best to use a smart pointer for the reference counting?

Also does the above code produce any memory leaks in that matter or was the data being copied in a clean way into the list until it gets properly deleted out of the list with erase()/clean()/pop_front()/pop_back?

Or to put it in another way - is the above code also usable for me or should I avoid coding like this? :P
Last edited on
It's not so simple to use a smart pointer for reference counting.
and no, it doesn't get a memory leak, but the pointer in pointer_list is nomore valid.

Your idea should be like using only one of the twos:

1
2
std::list<Object*> ptrlist;
ptrlist.push_back(new Object( /*...*/ )); // No copy constructor of Object called, the faster way 


Or:
1
2
std::list<Object> objlist;
objlist.push_back(Object( /*...*/ )); // Copy constructor of Object called, slower 
EssGeEich wrote:
..but the pointer in pointer_list is nomore valid.
Yeah I just did both lists in the same code to try out if the data in either list is actually affected when deleting the object.

In my application I will of course use only one of them.

Anyway, thanks for the quick help ;)
Ah, I forgot a thing:

In case you use the first example i showed you up ( std::list<Object*> ptrlist; ) When you delete the std::list you should delete all the internal pointers. Or you can use a smart pointer but you will not be using reference counting ( std::list< std::auto_ptr< Object > > ptrlist; )
You mean I should manually call delete for each entry in the list?

But doesn't clear() do that for me?

http://www.cplusplus.com/reference/list/list/clear/
Removes all elements from the list container (which are destroyed), and leaving the container with a size of 0.
Last edited on
It calls the destructor, but if it's a pointer you manually allocated, you must manually destroy it too, unless you use std::auto_ptr.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

{
    std::list<Object*> ptrlist;
    ptrlist.push_back(new Object());
} // <- ptrlist destructor called, let's follow:

/*
1. ptrlist.~std::list<Object*>();
2. ptrlist[0].~(Object*)();

Here, the destructor is the (Object*) destructor,
Not the Object destructor itself! This results in a memory leak!
If before ptrlist was destroyed you did:

delete ptrlist[0]; (Or whatever it was)

That was going to result to call

ptrlist[0]->~(Object)();

Notice also the difference over from a '.~' and '->~'.

*/
Last edited on
So doing it like this would be fine (no memory leaks)?
1
2
3
4
5
6
7
8
std::list<Object*> ptrlist;
ptrlist.push_back(new Object());

Object* PointerToObject = ptrlist.back(); //I use the pointer here because it makes things easier for me in my code (less text)
/*doing some stuff here*/

delete PointerToObject;
ptrlist.pop_back();


edit: sadly I can't call the list entries by index but I can iterate through it so that should be fine too
Last edited on
If you want to access the elements with index you should consider using std::vector instead of std::list.
No I don't need to access the indices, I just said that because EssGeEich used that in his commented code so I wanted to point that out.

I'm fine with using std::list ;)
Last edited on
EssGeEich is correct in that you should use a smart pointer so you do not have to manually delete these objects.

However you should not use auto_ptr because it's deprecated (and it doesn't even work when used in standard containers). Replace it with unique_ptr or shared_ptr.
Last edited on
Zapeth wrote:
sadly I can't call the list entries by index but I can iterate through it so that should be fine too

It's me who isn't used to std::, but yeah, for each element that gets removed, you need to call delete on it, so that example works.

Not doing this won't result in an error, but in a memory leak.
Okay, thanks again for explaining everything to me :)
Topic archived. No new replies allowed.