views:

135

answers:

6

If I have a list<object*>>* queue and want to pop the first object in the list and hand it over to another part of the program, is it correct to use (sketchy code):

object* objPtr = queue->first();
queue->pop_first();
return objPtr;  // is this a pointer to a valid memory address now?

?

According to the documentation on http://www.cplusplus.com/reference/stl/list/pop_front/ it calls the destructor of the deleted element, but I'm confused as to whether it means the linked list's node object, or the actually stored "user" object.

Edit: I might be front instead of first, my bad.

+3  A: 

Yes, it is a valid pointer. List will not release the memory allocated by you. List will destroy its internal not the user object.

Naveen
A: 

Your code is well but it is better to use list< boost::shared_ptr<object> >.


   shared_ptr < object> objPtr = queue->first();
   queue->pop_first();
   return objPtr;  
Alexey Malistov
Why was this down-voted?
sbi
I didn't downvote but here's my opinion: You can't simply switch from native pointers to shared_ptr so this answer is not very useful.
mxp
Why is it better to use shared_ptr when you don't fully know the requirements.
VNarasimhaM
Because if someone doesn't know whether the list, when deleting the contained pointers, will also delete the pointed to objects, then that someone is _very_ unlikely to get manual memory management wrong?
sbi
@mxp: 1) It's certainly trivial in the code given. 2) IME experience switching to smart pointers is mostly non-trivial where the code does dubious things with naked pointers. 3) Using naked pointers in containers is bound to create leaks.
sbi
I downvoted it. And the reasons given above were mine for downvoting. boost::shared_ptr is neither an answer to the question nor it is objectively "better" than raw pointers. There are some applications where you don't need shared_ptrs. If they were always "better" then C++ would be garbage collected by default. It isn't because they are not always "better". Just because putting naked pointers into containers is more difficult doesn't make shared_ptrs automatic. And still, the question is not being answered.
jmucchiello
jmucchiello
@jmucchiello: There's an important differnece between smart pointers and GC: Destruction is still deterministic with smart pointers, while it kicks in non-deterministically with GC. I still believe that, for someone who doesn't know what happens to heap objects when a list deletes the pointers, smart pointers are the answer to their problem. I guess we just have to agree to disagree.
sbi
+3  A: 

Yes it's valid: Since you put pointers into the list, only the pointer gets destroyed, not the object itself.

mxp
A: 

When you remove the elements, STL containers will not destroy the user objects allocated on heap.

class A
{

};


list<A*> PointerToObjectList;

A* ptr = new A();
PointerToObjectList.push_back(ptr);

If you remove the ptr from the list, list will not delete the object automatically. You need to explicitly call delete once the object is no longer being used.

aJ
+2  A: 

Yes objPtr contains pointer to a valid memory.

When you insert an element into a std::list, list makes a copy of it. In your case the element is an address (a pointer) so list makes a copy of the address and stores it.

object * optr = queue->pop_front();

optr now points to the object

queue->pop_front();

removes the element (an address/pointer) from the list, optr already points to your object.

After you're done with the object don't forget do delete it otherwise you end up with memory leak.

Example:

#include <iostream>
#include <list>

using namespace std;

struct A
{
    static int count;

    A() : val(count++) { cout << "A(" << val << ")" << endl; }
    ~A()               { cout << "~A(" << val << ")" << endl; }

    int val;
};

int A::count = 0;

ostream& operator<<(ostream& os, A& a) { return os << a.val; }

int main()
{
    list<A*> alist;

    for (unsigned int i = 3; i; --i) alist.push_back(new A());
    for (unsigned int i = 3; i; --i)
    {
        A * aptr = alist.front();
        alist.pop_front();
        cout << *aptr << endl;
        delete aptr;
        aptr = 0;
    }
}
stefanB
+1  A: 

The standard indeed says (23.2.2.3/5) that the destructor of the element's type is called. But this type is a pointer here, and the destructor of a pointer does nothing...

Xavier Nodet