I'm trying to figure out, what happens if you create a shared pointer, that points to an object that is held in a vector.
The Code looks like this:
class TestObject
{
public:
int someTestData;
};
class Test
{
public:
std::shared_ptr<TestObject> testPointer;
std::shared_ptr<std::vector<TestObject>> getTestVector()
{
return testVector;
}
private:
std::shared_ptr<std::vector<TestObject>> testVector;
};
The Problem is, that I want to both support fast iteration over all TestObjects, but also provide shared pointers to single objects in the vector.
But now I dont know what happens if the last shared ptr to an object in the vector gets deleted.
Does the object get removed from the vector?
Does this cause undefined behaviour?
How can I archieve the behaviour I want if this doesnt work?
EDIT:
To Clarify, what i need:
I need a MemoryManager Class, that has a method CreateTestObject, that creates a new TestObject, stores it in a vector or some other container that supports fast iteration and returns a some kind of shared_ptr to the newly created object so that the object that needs a new TestObject has a reference.
Now i also need the shared_ptr to the TestObject to be able to remove the TestObject from the container it is stored in, when the last shared_ptr goes out of scope, so that i'm not left with a vector full of unused TestObjects.
It's hard to know what happens on your end, since you didn't share the code which actually initializes testPointer. But what you're looking for is an aliased std::shared_ptr:
testPointer = {testVector, &(*testVector)[0]};
From then on, testPointer points to the first element of the vector, but shares the ownership of the vector itself with testVector, providing the correct semantics.
Do note that this doesn't prevent the vector from relocating its storage and making testPointer dangle if you cause it to reallocate.
For the record, trying to construct a std::shared_ptr owning the element itself, as follows:
testPointer.reset(&(*testVector)[0]); // Wrong!
... will necessarily trigger UB down the line, since std::vector has unique ownership of its elements already, and there's no way that you can make std::vector or std::shared_ptr relinquish ownership.
"I'm trying to figure out, what happens if you create a shared pointer, that points to an object that is held in a vector."
That is a very bad idea because the position of any element of a vector can change simply by adding or removing an element to the vector. What you implement is simply a duplication of ownership which brakes basic OOP concepts.
Does the object get removed from the vector?
A shared pointer is the "owner" of the object and the vector is also the owner. So it is conceptional broken!
Does this cause undefined behaviour?
It is still undefined, as you generate dangling pointes because vector can move its objects.
How can I achieve the behaviour I want if this doesnt work?
You have already fast access via operator[] and you have already "pointers" as iterators can be used as any other pointer.
You can do this using a custom deleter with your shared_ptr and using a container like boost::stable_vector:
testVector.emplace_back();
auto it = V.end()-1;
auto deleter = [&testVector, it] (int*) {testVector.erase(it);};
std::shared_ptr<TestObject> ptr(&testVector.back(), deleter);
When the last shared_ptr to an object goes out of scope, it will remove it from TestVector. Note however, that this does not work the other way round: If the object is removed from TestVector through any other means (e.g. by TestVector going out of scope), this will trigger undefined behavior, so it is your responsibility to make sure that this does not happen. Note also that this does not work with std::vector, as the iterators get invalidated when the vector is resized. You could however use std::list, although that will probably be slower than stable_vector.
This is not the cleanest solution (due to the very real possibility of triggering UB if you're not careful), but doing this proberly would be much more involved.
Related
Suppose I had a Manager Class that held a vector of some object:
class SomeObjectManager
{
private:
std::vector<SomeObject> _heldObjects;
};
And in that class I had some function that iterated through said vector to return the requested object.
SomeObject getSomeObjectByName(std::string nameToFind);
What I need to know is when is it proper to use smart pointers. Should I actually be returning something like below?
std::shared_ptr<SomeObject> getSomeObjectByName(std::string nameToFind);
Or should I be using something else like unique_ptr or weak_ptr? I want the SomeObjectManager class to own the actual object being returned and never have said SomeObject be deleted unless the Manager makes it so.
I have only recently came back to the C++ world after being in C# mode for quite some time; thanks for the help and clearing up my confusion.
I have read a lot about this matter but never really found a straight answer to my particular situation.
Edit #1
I'd like to reword my last few sentences with this:
I want the SomeObjectManager class to own the actual object being returned and never have said SomeObject be removed from the vector and subsquently deleted, fall out of scope, until the Manager forces it to do so. For example:
void SomeObjectManager::removeSomeObjectByName(const std::string& objectToRemove);
This would just iterate over the vector, finding said SomeObject, and remove it from the Vector.
Since SomeObjectManager is the owner of the SomeObject instances (stored in its std::vector data member), I'd just return raw pointers, since they are actually observing pointers.
std::vector<SomeObject> _heldObjects;
SomeObject* getSomeObjectByName(const std::string& nameToFind) {
... find index of object corresponding to 'nameToFind'
return &_heldObjects[foundIndex];
}
(Note that I passed nameToFind using reference to const, since I assume that nameToFind is an input string, so if inside the method you are just observing that string, you can avoid deep-copies using const &).
You must pay attention when you have owning raw pointers (they should be wrapped inside safe RAII boundaries), but observing raw pointers are fine.
Just make sure that the lifetime of SomeObjectManager exceeds that of its clients, to make sure that the clients are referencing valid objects.
Note also that if you add new items to the vector data member (e.g. using std::vector::push_back()), the addresses of the previous SomeObject instances stored in the vector can change. So, if you gave pointers to those outside, they become invalid.
So, make sure that the vector size and vector content are not changed before you give pointers to its elements to client code outside.
An alternative would be to have std::vector<std::unique_ptr<SomeObject>> as data member. In this case, even if the vector is resized, the addresses you returned using the smart pointers (in particular using std::unique_ptr::get()) are still valid:
std::vector<std::unique_ptr<SomeObject>> _heldObjects;
SomeObject* getSomeObjectByName(const std::string& nameToFind) {
... find index of object corresponding to 'nameToFind'
return _heldObjects[foundIndex].get();
}
PS
Another option might be returning references to const SomeObject (assuming that this use of const makes sense in your design):
std::vector<SomeObject> _heldObjects;
const SomeObject& getSomeObjectByName(const std::string& nameToFind) const {
... find index of object corresponding to 'nameToFind'
return _heldObjects[foundIndex];
}
If your program runs in a single thread, you are mostly good with returning raw pointers or references to the objects that are stored in the vector, if you have sufficient discipline.
Since the manager privately owns the vector and the objects inside, and thus controls when objects are deleted, you can make sure that there remain no invalid pointers to objects that have been deleted (this isn't automatically guaranteed!).
Basically, the manager must only ever delete objects when it knows that nobody holds a reference to that object, for example by only doing this at distinct, well-defined times (such as at program end, or when it knows that no consumers remain, or such).
Reference counting is one way of doing that, and it is what shared_ptr does internally, too (well, no... strictly to the letter of the specification, reference counting isn't required, only the visible behavior is defined, but practially all implementations do it).
The process of "deleting" an object would thus merely decrement the reference counter (much like in a managed language) and the object would really cease to exist when the reference counter reaches zero. Which is probably but not necessarily immediately the case when you "delete" it. It might as well take a few moments before the object is actually destroyed.
That approach works "automatically" without a lot of diligence and rigid discipline, and it can be implemented simply by storing shared_ptrs of your objects in the vector and returning either shared_ptrs or weak_ptrs.
Wait a moment! Then why are there even weak_ptrs if you can just return a shared_ptr too? They do different things, both logically and practically. shared_ptrs own (at least partially), and weak_ptrs do not. Also, weak_ptrs are cheaper to copy.
In a multi-threaded program, storing shared_ptrs and returning a weak_ptr is the only safe approach. The weak_ptr does not own the resource and thus cannot prevent the manager from deleting the object, but it gives the holder a reliable and unambiguous way of knowing whether the resource is valid and that the resource will remain valid while you use it.
You return that weak_ptr, and when the consumer actually wants to use the object, it converts the weak_ptr to a temporary shared_ptr. This will either fail (giving a null pointer) so the consumer knows that the object has been deleted, and it may not use it. Or, it will succeed, and now the consumer has a valid pointer with shared ownership of an object which is now guaranteed to remain valid while it is being used.
There is nothing in between "valid" and "invalid", no guessing, and nothing that can fail. If you successfully converted to a valid temporary shared_ptr, you are good to go. Otherwise, the object is gone, but you know that.
This is a big, big plus in terms of safety. Even if the manager "deletes" the object while you are using it, your program will not crash or produce garbage, the object remains valid until you stop using it!
Arguably, this somewhat blurs the "the manager deletes objects when it chooses to do so" paradigm, but it really is the only way of doing it safely. The manager is still the one in control of what objects to delete, it only cannot delete an object immediately while it is in use (which would possibly result in a terrible desaster). It can, however, at any time schedule the deletion for the next possible time by removing its shared_ptr and thus decrementing the reference count.
The only obvious showstopper is the case where an object must be destroyed immediately (because the destructor has side effects that must happen immediately without delay). But in this case, it is very hard (a nightmare!) to get concurrent access right. Luckily, that's a very rare scenario, too.
Return a reference (or regular pointer) to the SomeObject from your function. The reference is valid so long as it remains in the vector, and the vector is not reallocated (careful with that, maybe use a list instead or vector of unique_ptr). When removed from the vector, the object is dead and all references to it are no longer valid. (Again careful removing element in the middle)
If you are not storing your objects as std::shared_ptrs, then it wouldn't make any sense to return an std::shared_ptr. Not even sure how you are going to do it. I don't think there is a way to wrap an already existing pointer within a smart pointer. If you already have the data there, you can just return a regular const pointer to it. That way you will avoid the overhead that it takes to copy the object contents.
You have a choice of using shared_ptr or weak_ptr in this case. Which you use will depend on the lifetime you want for the object.
If you only want the object to be valid whilst the SomeObjectManager has a reference to it and a client is using it at that time then use weak_ptr. If you want a reference to remain valid if either the SomeObjectManager has a reference and a client stores a reference to it.
Here's an example with a weak_ptr.
std::weak_ptr<SomeObject> weakref = getSomeObject();
// weakref will not keep the object alive if it is removed from the object manager.
auto strongref = weakref.lock();
if ( strongref ) {
// strongref is a shared_ptr and will keep the object alive until it
// goes out of scope.
}
This can be useful in a multi-threaded environment as the shared_ptr reference count access is thread-safe. However, it does mean that a client can extend the lifetime of an object longer than you may like.
If you want to use smart shared pointers, the vector itself should use the smart pointer.
class SomeObjectManager
{
private:
std::vector<std::shared_ptr<SomeObject> > _heldObjects;
};
But then you're safe.
Suppose there's a vector of Items
vector<Item*> items; //{item1, item2, item3}
Then, in other part of the code,
items[1]->suicide();
where the suicide function is:
void Item::suicide()
{
delete this;
}
What is items vector size and how it's arrangement now?
It is okay to do this?
Edit (may I ask an additional question?): If the desired arrangement of the output is {item1, item3}, size is 2, and no dangling pointer, how to do it in a self-destructing way (from the item2 itself)?
Edit 2 : Thanks for all the answers! Awesome. So I finally decided and found the way to do it from outside of the object because it was a bad practice and unnecessarily complicated
What is items vector size and how it's arrangement now? The same. The function call does not change the vector contents nor size at all. It just frees the memory the pointer is pointing to.
Is it okay to do this? More precisely: Is it legal C++? Yes. Is it good style programming? No. Let me elaborate on the latter:
There should be a separation of concerns: Who's responsible for memory management? The container or the user of the class Item or the class Item itself?
Typically the container or user should do that, because he knows what's going on.
What's the way to do that? Memory management in modern and safe C++ code is mostly done using smart pointers like std::shared_ptr and std::unique_ptr and containers like std::vector and std::map.
If the class Item is a value type (that means you can simply copy it and it has no polymorphic behavior in terms of virtual functions), then just use std::vector<Item> instead for your code. Destructors will be called automatically as soon as an element is removed from the container. The container does it for you.
If the class Item has polymorphic behavior and can be used as a base class, then use std::vector<std::unique_ptr<Item>> or std::vector<std::shrared_ptr<Item>> instead and prefer the std::unique_ptr solution, because it adds less overhead. As soon as you stop referring to an object, it will be deleted automatically by the destructor of the smart pointer you are using. You (almost) don't need to worry about memory leaks anymore.
The only way you can produce memory leaks is that you have objects that contain std::shared_ptrs that refer to each other in cyclic way. Using std::unique_ptrs can prevent this kind of trouble. Another way out are std::weak_ptrs.
Bottom line: Don't provide a function suicide(). Instead put the responsibility solely into the hands of the calling code. Use standard library containers and smart pointers to manage your memory.
Edit: Concerning the question in your edit. Just write
items.erase( items.begin() + 1 );
This will work for all types: std::vector of values or pointers. You can find a good documentation of std::vector and the C++ Standard library here.
The suicide member doesn't change the vector. So the vector contains an element which is an invalid pointer and formally you can't do much with an invalid pointer, even copying or comparing it is undefined behavior. So anything which access it, included vector resizing, is an UB.
While any access if formally UB, there is a good chance that your implementation doesn't behave strangely as long as you don't dereference the pointer -- the rationale for making any access UB is machines where loading an invalid pointer in a register can trap and while x86 is part of them, I don't know of widespread OS working in this mode.
Your suicide function does not to anything with the Items vector, let alone it knows anything about it. So from the vector's point of view: nothing changes when you call the function and it's ok to do that.
The pointer will become invalid, that's all. You should be careful to not to delete it again. vector<Item*> will NOT delete elements on its own.
The vector has no idea what you're doing elsewhere in the code, so it'll keep a dangling pointer to the original Item.
"Is it OK do do that?"
After suiciding the item, you should adjust the vector manually to no longer keep that dangling pointer.
That's ok in case of vector of pointers as vector will not call Item's destructor. But you have to somehow know which pointers are still valid.
If you are storing Items in vector by value, calling Item's destructor is not ok. When vector will be destroyed or cleared, it will call item's destructor again, causing application crash.
Wow, It seems that you make a typing error. It should be vector<Item *> Items;
As to your question:
the size of vector Items does not change, means that, it still has three pointers to Item objects.
the content of the vector does not change:
before Items[1]->suicide() , Items[0] = 0x000001, Items[1] = 0x000005, Items[2] = 0x000009
after Items[1]->suicide(), Items[0] = 0x000001, Items[1] = 0x000005, Items[2] = 0x000009
It's definitely OKAY to do so.
Besides, the vector will manage its memory automatically, when you push some elems into it while the capacity is not enough, it will reallocate a larger space, BUT, when you pop some elems or erase some elems, it will never give the redundant memory to the system.
The code of Items[1]->sucide() just return the memory held or pointed by the pointer Items[1] to the system, it will do nothing on the pointer itself, Items[1] still holds the same value, but point an unsafe area.
Unexpectedly, you have made a Design Pattern, suppose you want to design a class and you ONLY allow allocate any object of it on the Heap, you may write the following code:
class MustOnHeap
{
private:
~MustOnHeap() { // ...}
public:
void suicide() { delete this;}
};
Then ,the class can not have any instance that is alloacated on the stack, because the destructor is private, and the compiler must arrange the calling of destructor when the object walk out its scope.
Therefor, you must allocate them on the heap, MustOnHeap* p = new MustOnHeap; and then destroy it explicitly : p->suicide();
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.
I am coming from a C# background to C++. Say I have a method that creates a object in a method on the stack, then I pass it to another classes method which adds it to a memeber vector.
void DoStuff()
{
SimpleObj so = SimpleObj("Data", 4);
memobj.Add(so);
}
//In memobj
void Add(SimpleObj& so)
{
memVec.push_back(so); //boost::ptr_vector object
}
Here are my questions:
Once the DoStuff methods ends will the so go out of scope and be popped from the stack?
memVec has a pointer to so but it got popped what happens here?
Whats the correct way to pass stack objects to methods that will store them as pointers?
I realise these are probably obvious to a C++ programmer with some expereince.
Mark
Yes.
The pointer remains "alive", but points to a no-longer-existent object. This means that the first time you try to dereference such pointer you'll go in undefined behavior (likely your program will crash, or, worse, will continue to run giving "strange" results).
You simply don't do that if you want to keep them after the function returned. That's why heap allocation and containers which store copies of objects are used.
The simplest way to achieve what you are trying to do would be to store a copy of the objects in a normal STL container (e.g. std::vector). If such objects are heavyweight and costly to copy around, you may want to allocate them on the heap store them in a container of adequate smart pointers, e.g. boost::shared_ptr (see the example in #Space_C0wb0y's answer).
Another possibility is to use the boost::ptr_vector in association with boost::ptr_vector_owner; this last class takes care of "owning" the objects stored in the associated ptr_vector, and deleting all the pointers when it goes out of scope. For more information on ptr_vector and ptr_vector_owner, you may want to have a look at this article.
To achieve your goal, you should use a shared_ptr:
void DoStuff()
{
boost::shared_ptr<SimpleObj> so(new SimpleObj("Data", 4));
memobj.Add(so);
}
//In memobj
void Add(boost::shared_ptr<SimpleObj> so)
{
memVec.push_back(so); // std::vector<boost::shared_ptr<SimpleObj> > memVec;
}
Yes your so object will be popped off the stack once your function leaves scope. You should create a heap object using new and add a pointer to that in your vector.
As said before, the pointer in your vector will point to something undefined once your first function goes out of scope
That code won't compile because inside the Add function you're trying to trying to push a whole object into a vector that expects a pointer to an object.
If instead you were to take the address of that object and push that onto the vector, then it would be dangerous as the original object would soon be popped off the stack and the pointer you stored would be pointing to uninitialised memory.
If you were using a normal vector instead of a pointer vector then the push_back call would be copying the whole object rather than the pointer and thus it would be safe. However, this is not necessarily efficient, and the 'copy everything' approach is probably not intuitive to someone from the C#, Java, or Python worlds.
In order to store a pointer to an object it must be created with new. Otherwise it will disappear when going out of scope.
The easiest solution to your problem as presented here would be to use std::vector instead of boost::ptr_vector, because this way the push_back would copy the object in the vector
What I am trying to do is essentially create two vectors of objects, where some objects are entered into both lists and some are just entered into one. The first problem I found was that when I used push_back() to add an object into both lists the object was copied so that when I changed it from one list the object did not change in the other. To get around this I tried to create a list of pointers to objects as one of the lists. However when I accessed the pointer later on the data seemed to be corrupted, the data member values were all wrong. Here are some snippets of my code:
Definition of vectors:
vector<AbsorbMesh> meshList;
vector<AbsorbMesh*> absorbList;
...
Adding an object to both:
AbsorbMesh nurbsMesh = nurbs.CreateMesh(uStride, vStride);
// Add to the absorption list
absorbList.push_back(&nurbsMesh);
// Store the mesh in the scene list
meshList.push_back(nurbsMesh);
Accessing the object:
if (absorbList.size() > 0)
{
float receivedPower = absorbList[0]->receivedPower;
}
What am I doing wrong?
There's some details missing, but at a guess.
nurbsMesh goes out of scope between the push_back and the absorbList[0]->receivedPower.
So now your vector of pointers contains a pointer to an object that doesn't exist anymore.
Try adding a copy constructor to your AbsorbMesh class and adding to your vector like this.
absorbList.push_back(new AbsorbMesh(nurbsMesh));
meshList.push_back(nurbsMesh);
don't forget to delete the objects in absorbList, like this
for(vector<AbsorbMesh*>::iterator it = absorbList.begin(); it != absorbList.end(); it++) {
delete it;
}
Or store a shared pointer in your vector instead of a bare pointer. Boost has a good shared pointer implementation if you're interested. See the docs here
If you want to have updates to items in one vector modify objects in the other vector, then you'll need to store pointers in both vectors.
Using your original requirements (updating an item in one vector affects items in the other vector, here's how I'd do it with a boost shared pointer. (WARNING, untested code)
vector<boost::shared_ptr<AbsorbMesh> > meshList;
vector<boost::shared_ptr<AbsorbMesh> > absorbList;
boost::shared_ptr<AbsorbMesh> nurb = new AbsorbMesh(nurbs.CreateMesh(uStride, vStride));
meshList.push_back(nurb);
absorbList.push_back(nurb);
...
...
if (absorbList.size() > 0)
{
float receivedPower = absorbList[0].get()->receivedPower;
}
You are storing the address of an object allocated on stack. The nurbsMesh object gets destroyed as soon as your method which does push_back() ends. If you try to access this pointer afterwards the object is already destroyed and contains garbage. What you need is to retain the object which remains even after the function goes out of scope. To do this allocate the memory for the object from heap using new. But for every new you should have a corresponding delete. But in your case you'll have problems deleting it as you are pushing the same pointer into two vectors. To solve this, you would require some type reference counting mechanism.
Object is deleted when you try get pointer from vector.
Try do
vector.push_back(new Object);
Once you have fixed the problem that others mentioned (storing a pointer to an object that's on the stack), you're going to run into another issue. A vector may reallocate, which results in its contents moving to another location.
The safe way to do this, then, is to store pointers in both vectors. Then, of course, you need to ensure that they get deleted... but that's C++ for you.
absorbList.push_back(&nurbsMesh); is wrong
absorbList save pointer to local object. When nurbMesh is destroyed you can not write
absorbList[0]->
However when I accessed the pointer later on the data seemed to be corrupted
When you put something on a vector, the vector might move it from one physical location to another (especially e.g. when the vector is resized), which invalidates any pointer to that object.
To fix that, you'll need to store a pointer (possibly a 'smart pointer') in both vectors (instead of having one vector contain the object by value).
If you're going to do this, it might be a good idea to disable the object's copy constructor and assignment operator (by declaring them as private, and not defining them) to ensure that after an object is created it cannot be moved.
There are several things wrong with your example
AbsorbMesh nurbsMesh = nurbs.CreateMesh(uStride, vStride);
This object is allocated on the stack. It is a purely local object. This object is going to be destroyed when you reach the end of the current block surrounded by {}.
absorbList.push_back(&nurbsMesh);
Now you get the pointer to the object that most likely will be destroyed.
meshList.push_back(nurbsMesh)
And this copies an entirely new object on the vector.
It is equally wrong to push the object on the vector first and then push a pointer to the object on the vector using absorbList.push_back( &meshList.back() ) because vector::push_back will reallocate the whole vector, invalidating all pointers.
You might be able to create all AbsorbMesh objects first, push them onto a vector, and then get the pointers to these objects in the vector. As long as you don't touch the vector, you'll be fine.
Alternatively, create objects on the heap using new AbsorbMesh() but make sure to call delete on each pointer thus created. Otherwise you have a memory leak.
Third solution, avoid the trouble and use smart pointers that take care of object destruction for you.
First, as everybody else points out, you can't allocate objects on the stack (i.e., other than by new or something similar), and have them around after leaving the scope.
Second, having objects in an STL container and maintaining pointers to them is tricky, since containers can move things around. It's usually a bad idea.
Third, auto_ptr<> simply doesn't work in STL containers, since auto_ptrs can't be copied.
Pointers to independently allocated objects work, but deleting them at the right time is tricky.
What will probably work best is shared_ptr<>. Make each vector a vector<shared_ptr<AbsorbMesh> >, allocate through new, and at a slight cost in performance you avoid a whole lot of hassle.