this is a question about which class does a free on shared pointers.
So I have a class hierarchy, base and derivedA and derivedB and derivedC all from base. Base has some virtual functions.
I have a class, Holder, it has a collection that holds instances of derivedA, derivedB and derivedC. So an instance of Holder is created, instances of the derived classes are dynamically created and add their pointers to the containers. I add the pointers so I can iterate through the container and call base->virtualFunction. I new the objects because otherwise an instance created on the stack is destroyed when it goes out of scope.
class Base;
class DerivedA : public base;
class DerivedB : public base;
class DerivedC : public base;
class Holder {
std::vector<Base*> collection;
void add(Base* base);
}
Holder holder;
DerivedA* da = new DerivedA;
DerivedB* db = new DerivedB;
holder.add(da);
holder.add(db);
who is to call delete on da and db?
Any other way to design this for the deletion concern goes away?
Thanks
Reza
My question is first off, which class should be responsible to free the dynamically created the derived classes? The class the contains the list
The simpler way ? Change your vector to become aware of ownership.
boost::ptr_vector<Base>
is such a vector, especially suited for polymorphic data:
deep-copy through clone methods (just implement virtual Base* clone() const;)
automatic memory management
sugar coating on dereferencing iterator (yields a Base& instead of a Base*)
In C++11, another alternative could be std::vector< std::unique_ptr<Base> >.
If you use new, then you have to say delete to clean up.
Your design suffers from the problem that you store the result of new, which you absolutely must keep track of, in a container, and it is unclear what can happen to it there. The container may be emptied or replaced or copied at some other point. In the end, you have to clean up, but how do you determine what to clean up?
Your design is inherently non-local, which means that the task of tracking the pointers now requires full understanding of everything that you do to the container. This is a heavy maintenance burden and limits scalability.
The better design approach would be to wrap the result of new into a single-responsibility manager like shared_ptr or unique_ptr and store those in the container. That way, it is always completely clear who owns the manually allocated objects and who disposes of them should the reference become inaccessible or lost.
[Original Update:] As a suggestion for your original design, which may or may not be appropriate (depending on many other factors you're not telling us about), and notwithstanding all its shortcomings, you could make the Holder do the cleaning up, and specify in the contract that you promise to add only pointers that you created with new:
Holder::~Holder() {
for (auto it = collection.cbegin(); it != collection.cend(); ++it)
delete *it;
}
This requires a strong contract between the class and the user, so do be sure that you intend this, that you document it, and most importantly that you write or delete copy constructors and assignment operators.
If you are going to for manual memory management, you need to define who is going to be responsible for deleting.
One possibility is for Holder to assume ownership of the classes and then to clean up in ~Holder (calling delete for every element in the vector). But then you would also need to decide on how Holder is going to be copied (deep copy or flat copy). The second option would require you to keep track of all HolderS that have references to the same memory etc.
Short and simple: Go with a shared_ptr or avoid this situation all together. Those are available in C++11 enabled compilers or from the Boost libraries.
The responsibility to free the memory is of the class/method that knows whether those objects are still used/useful.
In your simple example code Holder only contains pointers to the objects, so he can't possibly know when to free the memory: the pointed objects could be still useful even after Holder holder is disposed.
What you try to do has been implemented in a sane and proven way by Boost Smart Pointers, I strongly recommend always to first look at boost.org if this hasn't been done by it, already.
Basically, class-wise, the level you use the "new" is the level you use the "delete".
In your case the allocated vars in the program are in "main" I guess, so the allocation is not part of the class behavior therefor no class should free them but the user himself.
Related
I'm making the mental transition from old school C++ to "modern".
I have a class factory that is used to make sure all instances of a certain class, foo, are maintained in a list. This list is used to process all foos in order.
This is in a legacy system that uses regular old pointers (new/delete) but I was thinking of turning them into shared_ptrs.
Will I still need a "RemoveMeFromList()" call in the foo's destructor or is there some magic I'm not aware of?
What I propose you in this case is to keep a vector of weak pointers (std::weak_ptr) in your factory:
std::vector<std::weak_ptr<foo>> foo_instances;
Now, with this vector, if one pointer goes out of the scope, it will be expired. So, you can remove the expired pointers next time that you process the vector. In other words, you do not need an explicit "RemoveMeFromList" method, but you can do the removal of expired pointers when you go for processing of the foo instances.
Will I still need a "RemoveMeFromList" call in the foo's destructor
Yes.
or is there some magic I'm not aware of?
No.
You could implement a custom container, that stores weak pointers to objects in shared ownership, and on every access, check whether the pointer is still valid. I don't know if this would be a good design for you (seems dubious).
This is in a legacy system that uses regular old pointers (new/delete) but I was thinking of turning them into shared_ptrs.
You have not really provided us with a lot to go on, but I suspect std::shared_ptr is not what you need. std::shared_ptr is used to "collaboratively manage" ownership by all copies of the pointer, and kill it when there are none. Such killing will not notify your "factory", or central repository, of foos. But since you actually have it, and you want it to keep track of the instances, just let it be the one owning them. At most, you could have the entities which get pointers/references to foo instances instead get wrappers which handle just ref-counting somehow. Your central foo repository will handle deletions - if they are at all necessary. It could recycle unused foos - reinitialize them and hand them out instead of really allocating anything new.
Again, sorry for the rather vague and abstract answer.
You could implement a solution with shared_ptr and weak_ptr as eerorika suggested by doing something like this. You might prefer this solution to unique_ptr if you don't want the Factory to be the owner of the objects which determines when things are invalid.
Your factory class could look something like this:
class Factory {
public:
std::shared_ptr<MyObject> create();
std::vector<std::weak_ptr<MyObject>>& getObjects();
private:
std::vector<std::weak_ptr<MyObject>> objects;
void cullInvalidObjects();
};
We simply create a weak_ptr from the shared_ptr of the object in the factory method:
std::shared_ptr<MyObject> Factory::create()
{
auto object = std::make_shared<MyObject>();
std::weak_ptr<MyObject> weakObject = object;
objects.push_back(weakObject);
return object;
};
The factory can have an internal method that culls objects that are no longer valid:
void Factory::cullInvalidObjects()
{
auto iter = objects.begin();
while (iter != objects.end())
{
if ((*iter).expired())
{
objects.erase(iter++);
}
}
}
and then when getting objects to work on them, you would probably want to cull the list before providing it:
std::vector<std::weak_ptr<MyObject>>& Factory::getObjects()
{
cullInvalidObjects()
return objects;
}
Alternatively, rather than culling you could just get the list and then check for validity in your functions that process it. This is probably not the best solution if you have a large number of invalid items.
void callSomeMethod(std::vector<std::weak_ptr<MyObject>>& objects)
{
for (auto wObj : objects)
{
auto sObj = wObj.lock();
if(p)
{
p->someMethod();
}
}
}
I have two class, one for storing base data, and the other for storing additional data as following:
struct AnimationState(){
virtual ~ AnimationState(){};
Vector3f m_spacialData;
float m_fTimeStamp;
}
And the derived class:
struct HermiteAnimationState() : public AnimationState{
virtual ~HermiteAnimationState(){};
Vector3f m_tangentIn;
Vector3f m_tangentOut;
}
My question: is how can I, at first, create an instance of HermiteAnimationState, and then upcast it to AnimationState for storing in a vector like this:
std::vector<AnimationState> m_vStates;
...
Lately, I can get the object AnimationState and downcast it to HermiteAnimationState for accessing the additional data (member m_tangentIn and m_tangentOut).
HermiteAnimationState* p = dynamic_cast<HermiteAnimationState*>(&m_vStates[i])
The way polymorphism works in C++ is that if B is a base class and D is derived from B, then:
a pointer to D can be used where a pointer to B is expected
a reference to D can be used where a reference to B is expected
What you can't do in C++ is actually use a value of type D in a context where a value of type B is expected. For example, you can't store derived objects in an array of base object. This makes sense when you consider that a derived object may have a different size from a base object.
Similarly, you can't store derived objects in a vector of base objects.
What you can do is store pointers to HermiteAnimationState in a vector of pointers to AnimationState. It's up to you how to manage the memory. For example, the following would be valid:
std::vector<AnimationState*> m_vStates;
HermiteAnimationState h_a_s;
m_vStates.push_back(&h_a_s);
...
HermiteAnimationState* p = dynamic_cast<HermiteAnimationState*>(m_vStates[i])
Since h_a_s is a local variable, it'll be destroyed automatically at the end of its scope.
But this is probably an unworkable approach, because you probably want the objects referred to by the vector elements to persist beyond the current scope. We can use std::unique_ptr for this purpose. A std::unique_ptr owns the object it points to, and as long as it stays alive, so does that object; and it deletes the object when it is itself destroyed. So a vector of std::unique_ptr objects behaves like a vector of objects themselves in terms of memory management. Now you can do
std::vector<std::unique_ptr<AnimationState*>> m_vStates;
m_vStates.emplace_back(new HermiteAnimationState);
...
HermiteAnimationState* p =
dynamic_cast<HermiteAnimationState*>(m_vStates[i].get());
(Note, however, that you can't copy this vector; you can only move it.)
Basically, you need to use some kind of reference to the pointed object because you need dynamic polymorphism.
The simplest but error-prone would be using "naked" pointers. The first thing that is problematic with this is that you have to do the destroying manually: containers will destroy the pointer, not what is pointed.
The safer way to do this is to use smart pointers, which are designed to do the destruction depending on a pre-fixed rule that the smart pointer embedd in it's type. The simplest one and certainly the best choice if you are doubting is std::unique_ptr, which can't be copied but can be moved. The other choice, which should be thought carefully about before being used, is the std::shared_ptr which is useful IFF you don't know when you should destroy these objects but you know it's when some systems will refer no more to it. Some other systems might just be observing that object, in which case std::weak_ptr.
Now, from reading your question, I think you are certainly processing a lot of these animation data. There is an obvious design issue there, I think, I might be wrong.
However, it looks like, if you have a lot of these AnimationState to manage, in a loop, you will get performance issues. This is common issues in games, mainly caused by "cache conherency".
What I would recommand in this case, would be to NOT use
inheritance: it's an invitation to the cpu to jump all over the place and trigger cache misses;
dynamic_cast: it's one of the few operations that are not guaranteed to end in a predictable time (with new and delete for example), which basically mean that if you are in a critical loop, you can lose a lot of time through it. In some cases, you can't avoid using dynamic cast (like when doing dynamic plugins), but in most cases, using it just because you have chosen to use inheritance is just wrong. If you use inheritance, then you should use virtual calls.
However, what I suggest is even more drastic: don't use inheritance at all.
Obviously, this is only an advice. If you are not doing something with a critical loop, it doesn't matter. I'm just worried because it looks like you are doing some inheritance for composition, which always have bad consequences both on readability of the code and performance.
Suppose a class A object should be part of a class B, then I have three ways of incorporating it insider class B:
Method 1:
class B
{
public:
B():objA() {};
~B() {};
A objA;
};
Method 2:
class B
{
public:
B():pobjA(0) {};
~B() { delete pobjA;}
A *pobjA;
};
Method 3:
class C
{
public:
B() {};
~B() {};
boost::shared_ptr<A> pObjA;
};
Then my question is: are there some guidelines I can follow when I put object A as part of Class B. Thanks.
If you want the object to be dinamically allocated when A is created then go for a dynamic new when you repute it is necessary. In that case remember to garbabe-collect with delete your object when A is destroyed otherwise you're gonna leak memory.
Using boost::shared_ptr takes care of garbage collection so you can skip the "delete" phase as long as you control the scope where the pointer is collected (nb. your code is bugged in the second step, you need to allocate before deallocate the object somehow)
The first method always allocates an object within the parent object's memory layout and frees it as the object is destroyed. Notice that you don't need the default constructor call in the initialization list if you have a no-arguments default constructor (or a default one)
If there's no reason to use a pointer, don't use a pointer: I'd go with the first option. Also notice that your RAII in the second example is completely broken, as it does not follow the rule of three.
If you need dynamic allocation you can use the third with boost::shared_ptr or std::shared_ptr.
I believe you're looking for the distinction between association, aggregation, and composition, and when it is appropriate to use them. There is no generic answer to that except for using the weakest relationship you can get away with. As far as using smart pointers, you would probably use them anywhere you'd otherwise use raw pointers but want to manage ownership more cleanly. The con to that is the overhead, the pro is the neatness.
Just a small addition to others:
If you care for compilation speed - go with pimpl idiom.
In your case it should be Method 3 (I would prefer unique_ptr though).
I am wondering what might be the best way to accomplish a design dilemma in C++ ...
I have a class, which contains member variables of type Base of another class, and the real objects that are created are created as Derived of Base.
The class does not need to modify these variables, it is only using them. Someone else is creating these variables. These Derived classes also need to go to container (std::vector, QList, etc) classes in my class, so they should perform proper copy construction and assignment.
So, I was wondering what might be the best:
Create the member variables as a Base* and let us manage them and the memory they use. This leads to the classical memory leak issues... Someone just forgets to delete the object when they are not using it anymore.
Create the member variables as a Base& and let's pray that they do not disappear when they go out of scope somewhere.
Having reference member variables is always a poor choice because the compiler generated assignment and move assignment do the wrong thing, or not what one would expect.
Stick to pointers or smart pointers for member variables.
#hansmaad is just right, if you have a problem in controlling life time of the object you should share its ownership with those who create or manage it.
You have 2 options:
1) boost::shared_ptr or std::tr1::shared_ptr
You can easily use this class for any type Base without changing Base, but if you are working in a multi threaded environment it is very hard to achieve thread safety for shared_ptr and do not forget if you create an object as shared using one of this classes you should not manage the life time of the object directly and it is not legal to create a new shared object from raw pointer and you should always copy construct shared object. for example:
boost::shared_ptr<Base> sharedObject( new Drived() );
boost::shared_ptr<Base> validCopy( sharedObject ); // Ok share ownership
Base* p = sharedObject.get();
boost::shared_ptr<Base> invalidCopy( p ); // Error, can't create new shared_ptr from raw pointer
2) boost::intrusive_ptr
You can easily make it thread safe and you can pass it as either raw pointer or smart pointer since it can constructed from raw pointer because reference counting is implemented in the class instead but you should change definition of the class and add you reference counting mechanism
I would go with pointers, both for your vectors (i.e., vector<Base *>, not vector<Base>) and your container class for the following reasons:
If you store the Derived objects in a vector, that vector may get re-sized, which causes all the objects to 'move' to new locations in memory. This would invalidate all outstanding pointers and references
If your container contains references, you are not able to copy it as easily as you would if it contains pointers, as references can only be bound when defined (so in the constructor via MyClass::MyClass(int &a) : memberA(a) {}, if memory serves)
Pointers can be changed via other means such as set methods as needed, and can be set to null in the event of an absence of information
As far as ownership goes, jrok was the first to say it: shared_ptr<> is your friend. Don't reinvent the wheel, just make use of the standard library to simplify things for you. The only thing you would need to worry about in that case is circular pointers (i.e., the object points to itself, so there is always a valid pointer).
The first thing to consider with reference member variables is whether your class (not Derived, the class that's going to have a data member that is a pointer or a reference to Base) needs value semantics (which is another way of saying, "copies and assigns properly").
If so, then reference member variables are more or less out of the question straight away, because they can't be reseated. There are some odd situations where you can use them anyway, but you might as well assume that you won't, and use pointers.
Reference data members are occasionally useful for types that have "entity semantics" (that is, they don't assign at all and may or may not copy), but still they don't gain you a great deal. They can also lure you into the error of writing a constructor that takes a const Base& parameter, and storing it in a reference data member[*].
Who owns the object (and is responsible for freeing it) is completely independent of whether you use a pointer or a reference. There's probably a general convention not to use references for things you own (and there should be a convention not to use raw pointers for things you own, you should choose or write a suitable smart pointer. Smart pointer classes can hold a raw pointer). But that is just convention. You shouldn't assume that you manage the memory if and only if you have a pointer.
Summary: use a pointer, then make a separate decision how the memory is managed.
[*] This is a mistake, because eventually someone will accidentally use a temporary object in an initializer, and then the instance of your class with its reference data member will outlive the temporary. For this reason, things that store references for use after they return shouldn't take const & parameters, even if they don't modify the object. They can take const * instead. In C++11 I suppose they might be OK if there is also an rvalue reference overload, to prevent the const& overload being selected for temporaries, but it's not something I've tried out yet.
You should think about ownership. Whe owns that objects? If there is no clear answer to this questions, you should use a std::shared_ptr<Base> (shared ownership). If there is one class that owns that objects and all others just use them, you could use a std::unique_ptr<Base>, a pointer container like boost::ptr_vector or if there is no polymorphism it that owning classes just the concrete instance. In all other classes you can use plain pointers (prefered as class members) or references (prefered as arguments, if null is not allowed) to that objects.
Case 1 - Shared ownership
class IWorkOnBaseObjects
{
std::vector<std::shared_ptr<Base>> mySubset;
};
class MeToo
{
std::shared_ptr<Base> iNeedThisOne;
};
Case 2
class HomeOfBaseObjects
{
std::vector<std::uniqe_ptr<Base>> baseObjects;
};
class IWorkOnBaseObjects
{
std::vector<Base*> mySubset;
};
Case 3
class A : public Base{};
class B : public Base{};
class HomeOfAObjects
{
std::vector<A> aObjects;
};
class HomeOfBObjects
{
std::vector<B> bObjects;
};
class INeedABaseObject
{
Base* thisOne;
};
If I have a factory, that creates an object and returns a pointer to it, what will be a better way to delete it:
By delete call in the "user" code, or by a new DestructObject function which I should have together with the factory?
In the general case, the factory might not use plain old new to allocate the object. It may use object and/or page pooling, malloc with placement new, or something even more exotic (memory mapping?). There are at least three ways to handle this that I can think of:
Have the factory supply a recycle method to be called when you are done with the object.
Return a smart pointer that knows how to do away with the object once no referers remain.
Implement a custom delete operator in the object itself.
I hesitate to recommend one over the other, since I haven't given it enough thought in the last five minutes to proffer a definitive opinion, but I would tend to favour the last option in combination with a regular smart pointer like boost/tr1::shared_ptr.
The best way to delete it manually would be not at all.
The following code provides an opportunity not to think about who should remove the newly created object.
class FooFactory
{
public:
static std::auto_ptr<Foo> CreateInstance();
};
// transmit ownership of created object from factory to 'a' variable
std::auto_ptr<Foo> a = FooFactory::CreateInstance();
// using the created object is not required
FooFactory::CreateInstance();
The most versatile solution for this problem is to derive your class from a base class that has a virtual "killing" function. Something like this:
class IDisposable {
public:
virtual void Release() = 0;
};
It's generally believed that polymorphic objects should have virtual destructors to support proper object cleanup. However this is incomplete, because it doesn't account for potentially different memory management of objects.
On the other hand this method doesn't require to use virtual destructors. It's now replaced by Release function that does both: invokation of the correct destructor and releasing the memory by the appropriate means.
takes care of the object destr
both: destruct
The object returned from the factory will implement this "interface".