Let's say I have a generic Object class, and a generic List class. I want to maintain a list of these Objects. Should I store them as List<Object>
or List<Object*>
?
If I use List<Object>
and I have a method like:
if(some_condition) {
Object obj;
myObjectList.append(obj);
}
And my list class only keeps a reference to the object, so as soon as that if statement terminates, the object is destroyed, and the object I pushed becomes invalid. So then I end up doing something like:
Object *obj = new Object;
myObjectList.append(*obj);
So that it doesn't get destroyed. But now the objects are undeletable, no? Because now they're stored safely in the List as Objects, not pointers to Objects, so I can't call delete on them... or will they automatically be destroyed when they're popped from the list?
In that case, I should probably use List<Object*>
and delete them from the list when I'm done with them, no?
So confused... I'm sure I have a fundamental misunderstanding here somewhere.
EDIT:
As mentioned in a comment boost::ptr_list is even better since it is more efficient and has the same net effect as a std::list<boost::shared_ptr<T> >
.
EDIT:
You mention that you are using Qt in your comment. If you are using >= 4.5 you can use Qt's QList
and QSharedPointer
classes like this:
QList<QSharedPointer<Object> > object_list;
object_list.push_back(QSharedPointer<Object>(new Object));
I would recommend you use std::list<>
. You also likely just want to store pointers to the objects so they aren't being copied all of the time.
So bottom line is:
Let's say you have a class named Object
. You should do this:
std::list<boost::shared_ptr<Object> > object_list;
object_list.push_back(new Object);
For c++11/14, no need for boost, just use the standard smart pointers:
std::list<std::shared_ptr<Object>> object_list;
object_list.push_back(std::make_shared<Object>());
By using shared pointers, the objects will get cleaned up automatically when they are removed from the list (if there are no other shared_ptr
S also pointing to it).
You could have a list<Object *>
. But given your experience level, I feel that a reference counted pointer would be much easier for you to work with.
In that case, I should probably use List and delete them from the list when I'm done with them, no?
Yes, this is a viable option, but I highly recommend smart pointers to avoid the "...and delete them from the list..." step entirely.
NOTE:
also the example code you gave:
Object *obj = new Object;
myObjectList.append(*obj);
is probably not what you wanted, this makes a new object on the heap, they puts a copy of that in the list. If there is no delete obj
after that, then you have a memory leak since raw pointers are not automatically delete
d.
In the first case the Object is copied and only the original is destroyed. The other instance is kept in the list.
In the second version you can use the List destructor to delete the stored objects.
as with "all" things there is no one answer - the devil's in the details of what you want to do, or what your constraints are.
If the objects are lightweight and do not involve deep copying it's going to be more efficient to store the little things as copies. Otherwise, the overhead of smartish pointers is more than is warranted. If you are polymorPHic then you could use templated lists.
if it's more important to minimize copying, and eliminate redundant code from template instantiations, then use a list of smart, shared pointers.
Or use a list of naked pointers, use new/delete, and be meticulous with your pointer ownership.
Any list will act like a list, so the choice of list implementation is dependent on factors you aren't enumerating here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With