Removing from STL std::queue without destructing the removed object? - c++

All the documentation I can find on the STL containers (both queue and list) say that for any of the remove functions the removed object's destructor is called. This means that I can't use std::queue any time I want a queue that's simply a list of objects needing some operation performed on them.
I want to be able to add objects to the queue when they are waiting in line for me to do something to them. Then I want to remove them from it when I've finished with them, without destroying the object in question. This doesn't appear to be possible from the documentation I've read. Am I misreading the documentation? Is there another type of queue in the STL other than the basic "queue" that doesn't call the removed object's destructor on a call to pop_front?
Edit to clarify: In my case I'm using a list of pointers. Something like this:
dbObject *someObject;
queue<dbObject *> inputQueue;
inputQueue.push_back(someObject);
...
dbObject *objectWithInput = inputQueue.front();
//handle object's input...
inputQueue.pop_front(); // Remove from queue... destroyed now?

If you put pointers to objects in the queue (and any other STL container), the pointers won't get deleted when you remove them.
To elaborate: when you use std::queue and remove an object the destructor of some_obj* is called. But the destructor for plain pointer (or any POD type - int, char, etc) is empty, no-op. The fine line here is that the destructor for some_obj* is very different from the destructor for some_obj.

STL containers have value semantics. When you push an object into an STL container, the STL container keeps it's own copy of the object, and when the object (internal copy) is removed from the container it is destroyed.
If you used a container of a proxy type, as raw pointers, smart pointers (shared_ptr, weak_ptr), or adapters (as boost::reference_wrapper), then the STL container will destroy the proxy but not the type. Choosing one over the others is usually a matter of how you want to deal with resources.
The most common idiom is using raw pointers, but they don't explicit who is in charge of destruction (the code that pulls from the container should delete the pointer, or the resource is handled somewhere else?).
Modern usage moves towards the shared_ptr approach, as it dilutes the ownership problem. The object will be guaranteed to be alive when you take it out of the container, and if nobody else holds a shared_ptr then the object will automatically be deleted when the local shared_ptr goes out of scope. Using a weak_ptr will keep the ownership in the original code, but will allow you to check for validity of the pointer (if it was deleted) before usage. This could allow you to avoid performing the operation on an object that will be removed right away.
The problem with the shared_ptr/weak_ptr approach is that it forces you to use shared_ptr to hold the original resource. This means that you will not be able to put a pointer into a subobject (member attribute) of another class without redesigning the class to hold the attribute through a shared_ptr, and that will have other implications (the attributes will no longer be contiguous in memory, more dynamic allocation operations will be required...)
A technique that is hardly seen is using adapters as boost::reference_wrapper<>. A reference wrapper is a proxy object that contains a reference to the original object and is itself copyable. The advantage over plain raw pointers is that reading the code it is clear that the resource is managed outside of the queue: the code that pulls data from the queue does not need to delete the object. The advantage over the smart pointer approach is that you do not need to redesign other parts of your system to use smart pointers. The disadvantage is that, as in the raw pointer approach, you must ensure that the lifetime of the referred object outlives the reference in the container manually.

class someobj_t {};
std::queue<someobj_t> q;
...
someobj_t ppd = q.front(); // ppd is not a reference
q.pop();
// ppd now contain removed object
If you don't want someobj_t to be copied you could use std::queue< shared_ptr<someobj_t> >.

How about using a list of pointers to the objects?

Think of item's in a container being "in-scope" of that container, when an item is removed from a container it is just like leaving the scope of a function. If the variable is a pointer nothing happens to the item when leaving the scope. If variable is a stack local then destructor will will be automatically called upon leaving the scope.
Storing pointers in containers have the same downfalls as allocating into a local raw pointer, the memory is not cleaned up automatically. In a function if you don't delete the pointer or transfer ownership by returning it then you have a memory leak.
When storing raw pointers in a container the ownership can become a bit ambiguous and leaks can easily happen. Take a look at tr1::shared_ptr and store those in the containers instead.
std::unique_ptr in C++0x would also be a good solution for storing a pointer in a stdlib container when it is available.

Related

Why is using vector of pointers considered bad?

Recently I've met with opinion that I shouldn't use vector of pointers.
I wanted to know - why I cant?
For example if I have a class foo it is possible to do this:
vector <foo*> v;
v.push_back(new foo());
I've already seen some people down voting such practices, why is that?
Storing plain pointers in a container can lead to memory leaks and dangling pointers. Storing a pointer in a container does not define any kind of ownership of the pointer. Thus the container does not know the semantics of desctruction and copy operations. When the elements are being removed from the container the container is not aware how to properly destroy them, when a copy operation is performend no ownership semanctics are known. Of course, you can always handle these things by yourself, but then still a chance of human error is possible.
Using smart pointers leaves the ownership and destruction semantics up to them.
Another thing to mention is that containers are divided into non-intrusive and intrusive contaiers - they store the actual provided object instead of a copy so it actually comes down to a collection of pointers. Non intrusive pointers have some advantages, so you can't generalize that pointers in a container is something that should be avoided in all times, still in most cases it is recommended.
Using an vector of raw pointers is not necessary bad style, as long as you remember that the pointers do not have ownership semantics. When you start using new and delete, it usually means that you're doing something wrong.
In particular, the only cases where you should use new or delete in modern C++ code is when constructing unique_ptr's, or constructing shared_ptr's with custom deleters.
For example, assume that we have an class that implemented an bidirectional Graph, a Graph contains some amount of Vertexes.
class Vertex
{
public:
Vertex();
// raw pointer. No ownership
std::vector<Vertex *> edges;
}
class Graph
{
public:
Graph() {};
void addNode()
{
vertexes.push_back(new Vertex); // in C++14: prefer std::make_unique<>
}
// not shown: our Graph class implements a method to traverse over it's nodes
private:
// unique_ptr. Explicit ownership
std::vector<std::unique_ptr<Vertex>> vertexes;
}
void connect(Vertex *a, Vertex *b)
{
a->edges.push_back(b);
b->edges.push_back(a);
}
Notice how i have an vector of raw Vertex * in that Vertex class? I can do that because the lifetime of the Vertexes that it points to are managed by the class Graph. The ownership of my Vertex class is explicit from just looking at the code.
An different answer suggests using shared_ptr's. I personally dislike that approach because shared pointers, in general, make it very hard to reason about the lifetime of objects. In this particular example, shared pointers would not have worked at all because of the circular references between the Vertexes.
Because the vector's destructor won't call delete on the pointers, so it's easy to accidentally leak memory. A vector's destructor calls the destructors of all the elements in the vector, but raw pointers don't have destructors.
However, you can use a vector of smart pointers to ensure that destroying the vector will free the objects in it. vector<unique_ptr<foo>> can be used in C++11, and in C++98 with TR1 you can use vector<tr1::shared_ptr<foo>> (though shared_ptr has a slight overhead compared to a raw pointer or unique_ptr).
Boost also has a pointer container library, where the special delete-on-destruction behavior is built into the container itself so you don't need smart pointers.
One of the problems is exception-safety.
For example, suppose that somewhere an exception is thrown: in this case, the destructor of std::vector is called. But this destructor call does not delete the raw owning pointers stored in the vector. So, the resources managed by those pointers are leaked (these can be both memory resources, so you have a memory leak, but they could also be non-memory resources, e.g. sockets, OpenGL textures, etc.).
Instead, if you have a vector of smart pointers (e.g. std::vector<std::unique_ptr<Foo>>), then if the vector's destructor is called, each pointed item (safely owned by a smart pointer) in the vector is properly deleted, calling its destructor. So, the resources associated to each item ("smartly" pointed to in the vector) are properly released.
Note that vectors of observing raw pointers are fine (assuming that the lifetime of the observed items exceeeds that of the vector). The problem is with raw owning pointers.
I will talk specifically about a vector of pointers that's responsible for managing the lifetime of the pointed objects, because that's the only case where a vector of pointers is clearly a questionable choice.
There are much better alternatives. Specifically:
std::vector<std::shared_ptr<foo>> v;
and
std::vector<std::unique_ptr<foo>> v;
and
boost::ptr_vector<foo> v; // www.boost.org
The above versions tell the user how the lifetime of the objects is taken care of. Using raw pointers instead can possibly lead to the pointers being deleted either more or less than once, especially if the code is modified over time, or if exceptions become involved.
If you use an interface like ´shared_ptr´ or ´unique_ptr´, this self-documents the lifetime management for the user. When you use raw pointers you have to be clearly document how you handle the lifetime management of the objects, and hope that the right people read the documentation at the right time.
The benefits of using vectors of raw pointers are that you have more flexibility in how taking care of lifetime management, and that you can possibly get rid of some performance and space overhead.
There is absolutely no problem in using a vector of pointers. Most here are suggesting smart pointers, but I just have to say, there is no problem with using a vector of pointers without smart pointers. I do it all the time.
I agree with juanchopanza that the problem is your example is the pointers come from new foo(). In a normal completely-valid use case, you might have the objects in some other collection C, so that the objects will automatically get destroyed when C is destroyed. Then, in doing in the process of doing in-depth operations on the objects in C, you might create any number of other collections containing pointers to the objects in C. (If the other collections used object copies that would be time and memory wasteful, while collections of references is expressly forbidden.) In this use case, we never want to destroy any objects when a collection of pointers is destroyed.

Removing objects from C++ containers without deleting them

I am using C++ std vector to store render objects for a simple scene graph implementation.I need an ability to add and remove render objects in run time from the scene graph.Adding is not a problem,for removing: reading docs for vector and other C++ containers it appears that when objects are popped their destructors are called.That is not what I need because I want to be able to re-add those objects later to the rendering loop.What are the possible solution to this problem?
Important detail I forgot to mention -I am using vector of pointers to the render objects.
It seems you're confused with the basic concept of object instances. When you add something to a vector, you don't move it into it, you copy it:
vector<string> vec;
string s;
vec.push_back(s);
vec[0] is not s, it's a copy of s. So when you remove it from the vector, s is not affected.
If you don't want copies, you should switch to pointers instead. You can them remove the pointers from the vector and the destructor of the object they point to will not be called.
Edit:
OK, it seems you're already using pointers. You said:
reading docs for vector and other C++ containers it appears that when
objects are popped their destructors are called
That is true. When you remove a pointer from the vector, the pointer is getting destroyed. That's what the docs mean. It doesn't mean that the object the pointer points to is getting destroyed:
vector<string*> vec;
string s;
vec.push_back(&s);
vec.pop_back();
s is not affected at all. What gets destroyed by the pop operation is the pointer that holds the address of s, not s itself.
So you're fine.
You need to be aware of ownership to make this work correctly. If the vector you are using is only temporary and only to observe objects, just use a vector of points.
std::vector<object*> x;
On destruction of that vector the objects that are being pointed to are unaffected.
If you want to share ownership, use a boost::shared_ptr or std::shared_ptr.
When a pointer is popped, no destructor is called. Notionally even primitive types have destructors, to explain what happens when they go out of scope. Destroying a vector of pointers is the same as having a bunch of local pointer variables go out of scope.
Reference-counted smart pointers are objects that overload the * and -> operators to behave like pointers. They do implement the destructor to destroy the pointed-to object, thus implementing ownership. But for a scene graph, that's probably unnecessary.

Raw Pointer in C++

I have a piece of C++ classes and I have the raw pointer to the objects. The pointer to the object would get passed down to the function. The problem is the underlying function might need to store the pointer at times in an STL container in which pointer to the object would be used later on. If I am not using shared_ptr, I am thinking of adding a bool flag to the class which indicates whether the caller of the function is responsible for deleting the object memory. Would that be fine?
Thanks.
Messy. And rife with many potential bugs that will keep you at work well past midnight on a Saturday.
Be clear and consistent about resource ownership. Either the vector owns the pointers, or some specific function owns the pointers, or smart pointers own pointers. Any mixing of these semantics will have the ultimate result of you tearing your hair out late at night.
The best solution is usually to use a reference-counted smart pointer. (As you probably already know all to well, you can't use std::auto_ptr) Barring that, create a class whose sole purpose in life is to allocate, deallocate and grant access to the vector's contained pointers. Any function that needs the contained object would go through your manager class to get to them.
STL containers will almost certainly take a copy of the object which you insert into it. When the object is removed from the container, the object will be destroyed.
If the default copy constructor is not sufficient (i.e. you need to do a deep copy of the object), you need to ensure you implement your own version which does the copy properly.

C++ std::queue::pop() calls destructor. What of pointer types?

I have a std::queue that is wrapped as a templated class to make a thread-safe queue. I have two versions of this class: one that stores value types, one that stores pointer types.
For the pointer type, I'm having trouble deleting the elements of the queue on destruction. The reason is that I don't know a way to remove the items from the queue safely.
This reference states (vacuously, so I guess it doesn't actually STATE it) that the only way to remove elements from the queue is to call pop(). The reference also says that pop() calls the destructor for the item.
Well, this causes problems with my pointer types because they may or may not actually point to aggregates. If one of them points to an aggregate, they all will, but because the wrapper is templated, there is no guarantee which type (aggregated or non-aggregated) we are dealing with.
So, when pop() calls the destructor, what happens? How do I ensure that everything is being removed and the memory deallocation properly?
Lastly, my solution is using an older version of GCC for ARM9. I don't have control over this. I understand that there are libraries that have smart pointers and containers that would assist here, but they are off-limits for me.
Pointers themselves don't actually have destructors, so calling pop() on a queue containing a pointer won't call the destructor of the object your pointer points to.
Online sources are worth what you pay for them - get a proper reference like Josuttis's book. pop() does not "call the destructor" - it simply removes an element from the queue adaptor's underlying representation (by default a std::deque) by calling pop_front() on it. If the thing being popped has a destructor, it will be used when the popped object goes out of scope, but the queue class has nothing to do with it.
"How do I ensure that everything is being removed and the memory deallocation properly?"
If you absolutely have to store pointers in your queue, and you want them to be automatically freed when they're poped, then instead of a queue of pointers, you need a queue of objects which store a pointer, and delete it in their destructor. You could for example use a queue of shared_ptr. shared_ptr isn't in the standard library, but it's part of TR1 and is widely available.
Otherwise, it's the responsibility of the caller to delete the object:
T *off = q.front();
q.pop();
delete off;
The summary is that containers of pointers to dynamically allocated objects are a bit awkward. If you can design your program so that containers store copies of your objects, instead of pointers to dynamic objects, then do so. Failing that, you're responsible for resource ownership, not the container. STL containers know nothing about ownership, they just copy and destroy their value_type. Copying and destroying pointers does nothing to the objects they point to.

Memory management with new keyword and an STL vector of pointers

How is the destructor for the vector managed when adding elements to this list? Is the object destroyed correctly when it goes out of scope? Are there cases where it would not delete the object correctly? For example what are the consequences if "table" was a child of object, and we added a new table to a vector of object pointers?
vector <object*> _objectList;
_objectList.PushBack(new object);
Since you're making a vector of "bare" pointers, C++ can't possibly know that the pointers in question are meant to have "ownership" of the objects they point to, and so it will not call those objects' destructors when the pointer goes away. You should use a simple "smart" pointer instead of a "bare" pointer as the vector's item. For example, Boost's shared_ptr would be perfectly adequate for the task (although you can surely do it with "cheaper", lighter-weight approaches, if you don't want to deal with Boost as a whole and have no other need for smart pointers in your code).
Edit: since you (the OP) say that using a framework such as Boost is not feasible, and a couple comments usefully point out that even wrapping std::auto_ptr doesn't really qualify as a decent shortcut, you may have to implement your own smart pointers (or, if you find an open-source, stand-alone smart pointer template class that looks usable, audit it for compliance with your requirements). This article is a useful primer to smart pointers in C++, whether you have to roll your own or audit an existing implementation.
You could use bost 'ptr_vector'. It will automatically destruct objects that the items point to when they are either deleted or the instance of ptr_vector goes out of scope. More info is available here.
In your case, the object pointers are destroyed properly, but the actual objects themselves won't be touched. The STL properly destructs all contained elements - but will not implicitly dereference pointers to types.
STL Vectors make a copy of whatever you put in there, and ultimately delete that copy.
So in this case, the vector is storing a pointer to an object - not the object itself. So it makes a copy of the pointer, and deletes the pointer. But, as Chris said, the object itself will not be deleted.
So, solutions:
If you don't really need to use pointers, then don't:
vector <object> _objectList;
_objectList.PushBack(object());
If you do need to use pointers, you can either use a smart pointer (which handles reference counting for you, and will delete the object along with the pointer), as Alex suggested, or use a ptr_vector, as Igor mentioned.