10

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.

Michael IV
  • 11,016
  • 12
  • 92
  • 223
  • 3
    Store smart pointers to objects managed from somewhere else. – juanchopanza Nov 25 '12 at 10:03
  • 2
    Wouldn't copying them before you delete them be a solution? Or, in case of C++11, moving them out? – jogojapan Nov 25 '12 at 10:03
  • 1
    @juanchopanza I'd say either "smart pointers" or "managed from somewhere else", can't see how these two could mix. – Kos Nov 25 '12 at 10:04
  • Using smart pointers prevents the object destructors from being called? – Michael IV Nov 25 '12 at 10:12
  • @MichaelIV with the appropriate smart pointer, the last-man-out will release the object and fire the destructor. (std::shared_ptr is probably what you're looking for). – WhozCraig Nov 25 '12 at 10:15
  • Add some example code. Once an object has been removed from a container, the object no longer exists, so wanting to re-add it later makes no sense. The only thing that can exist are copies of that object, those copies will not be destroyed, and can themselves be copied into a new container at a later stage. You seem to have a non-problem here. – Mankarse Nov 25 '12 at 10:16
  • possible duplicate of [Does std::list::remove method call destructor of each removed element?](http://stackoverflow.com/questions/4260464/does-stdlistremove-method-call-destructor-of-each-removed-element) – fredoverflow Nov 25 '12 at 12:51

3 Answers3

11

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.

Nikos C.
  • 50,738
  • 9
  • 71
  • 96
  • Yes I know it :) I forgot to mention I am using vector of pointers. – Michael IV Nov 25 '12 at 10:19
  • 1
    @MichaelIV: The pointers will be destroyed, but the things that they point to will not be. (So you are fine as long as you properly manage the lifetimes of the objects being pointed to). – Mankarse Nov 25 '12 at 10:20
  • 2
    @MichaelIV Then you don't have a problem; when you remove the pointer from the vector, only the pointer is destroyed, not the object the pointer points to. – Nikos C. Nov 25 '12 at 10:21
  • @MichaelIV Concur with Nikos. If your vectors are holding pointers already, you likely don't need smart pointers assuming your memory is managed properly wherever the objects *really are*. But you should also not be seeing the destructions your seeing in that sense either. – WhozCraig Nov 25 '12 at 10:22
  • @MichaelIV I updated the answer to explain what the docs mean when they say that popped objects are destroyed. – Nikos C. Nov 25 '12 at 10:28
3

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.

pmr
  • 58,701
  • 10
  • 113
  • 156
1

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.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • The documentation of std:: containers pop() explicitly states "This calls the removed element's destructor.". That seems to contradict your statement. – foo Nov 04 '22 at 22:29