How would one go about creating a vector that includes both the base class as well as any derived classes?
For example, in a chess engine, I currently have a Move class which stores a particular move and a few functions to help it. In order to save memory, as millions of these objects are going to be created, I also have a derived class CaptureMove that extends the Move class storing a bit more information about what and where the piece was captured.
From what I can gather, pointers to Move objects should work, but I'm not quite sure on how to go about it.
The question is quite broad. Here some ideas:
Vectors of base pointers:
This works extremely well if your class is polymorphic (i.e. the relevant functions of the base class are virtual).
vector<Move*> mp;
mp.push_back (new Move); // attention, you have to delete it ofr memory will leak
mp.push_back (new CaptureMove);
It the simplest way to proceed. However you have to make sure that when you add an object, it's allocated properly (e.g. created with new), and that once you no longer need it, you delete it. This can be very cumbersome, especially if vector was copied and some of its pointers are still in use.
This approach can be practical for example if you create and delete the objects in a centralised manner, so that the vector only uses pointers which are properly managed somewhere else.
Vector of shared base pointers:
vector<shared_ptr<Move>> m;
m.push_back(make_shared<Move>());
m.push_back(make_shared<CaptureMove>());
m.push_back(make_shared<Move>());
Here an online demo.
It extends the pointer solution, using smart pointers to take care of the release of unused objects.
Honestly, it's a little overhead but it's really worth it, in order to have reliable code. This is the approach I would take personnally if I'd have to do it.
Vector of compound object
You could also prefer to store the object instead of a pointer to the object. While the idea seems simple, it's more difficult to do, because different derivates could have different size. And it has serious drawbacks, because you'd need to know all possible base and derived types you may store in the vector, which makes this approach less flexible.
You could certainly manage this with a complex union, but the easiers way would be to use boost::variant.
vector<boost::variant<Move, CaptureMove>> m;
This approach is only worth considering if the number of derived classes is very limited, but you have huge numbers of small objects (so that memory allocation would become a real overhead) of almost the same size.
Related
I have a class called Widget. This class is abstract and has virtual methods. To avoid object slicing all Widgets are stored as references or pointers. I have several classes with constructors that store internally the widget given to them; thus the Widget stored must have been initialized outside the constructor and cannot be destroyed before the object is, therefore usually the Widget is allocated via dynamic memory. My question is regarding how to handle this dynamic memory; I have compiled a list of options (feel free to suggest others.) Which is the most idiomatic?
1. Smart pointers. Smart pointers seem like the right choice, but since I'm using C++98 I have to write my own. I also think that writing smart_pointer<Widget> all the time is a little ugly.
2. Copy Widgets when stored. Another course of action is to store a copy of the passed-in Widget instead of the original. This might cause object-slicing, but I'm not sure. Also, users might want to write classes themselves that store passed-in Widgets, and I wouldn't want to make it too complicated.
3. Let the user handle everything. I could perhaps make the user make sure that the Widget is deleted on time. This seems to be what Qt does (?). However, this again complicates things for the user.
I personally like this approach (it is not always applicable, but I used it successfully multiple times):
class WidgetOwner
{
vector<Widget*> m_data;
public:
RegisterWidget(Widget *p) { m_data.push_back(p); }
~WidgetOwner() { for (auto &p : m_data) delete p; }
};
This simple class just stores pointers. This class can store any derivatives of Widget provided that Widget has virtual destructor. For a polymorphic class this should not be a problem.
Note that once Widget is registered, it cannot be destroyed unless everything is destroyed.
The advantage of this approach is that you can pass around pointers freely. They all will be valid until the storage will be destroyed. This is sort of hand made pool.
Which is the most idiomatic?
The most idiomatic would certainly be what next versions of c++ decided to be "the way to go", and that would be smart pointers (You can find/use an implementation on boost for example, also other ones on the internet might be simpler for inspiration).
You can also decide that since you are using c++98 (that's a huge factor to take into consideration), you take what's idiomatic for that context, and since that was pretty much no man's land, the answer is most likely whatever home made design is the most appealing to you.
I think smart pointer is best choice. And if you feel template is ugly, try the typedef
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.
I have been given some code to read which does some geometric operations on meshes.
A mesh data structure, by definition, should contain at least the information
regarding the coordinates of points, edge connectivity and face information.
So, the code given to me has classes to define vertex, edge and face data structure,
named respectively as Vertex, Edge and Face.
However the mesh class looks like this.
class basemesh
{
public:
/* Methods to operate on the protected data below.*/
protected:
/*! list of edges */
std::list<Edge*> m_edges;
/*! list of vertices */
std::list<Vertex*> m_verts;
/*! list of faces */
std::list<Face*> m_faces;
}
My question: Why does the mesh data structure store a list of pointers rather than a
list of the corresponding objects themselves.
e.g why not say directly std::list<Vertex>
I have seen this construct being used in a couple of other C++ codes
Does this have something to do with inheritance of classes? Or is it something to do
with performance with regards to iterating on the list?
This basemesh class is, as the name suggests, a base class from which
other specialized meshes are derived.
There is no performance reasons here. Its simply a case of ownership sharing. Remember this as a rule of thumb: Pointers in C++ are used to share/pass ownership of a resource, or to provide polymorphic behaviour through dynamic binding.
People is talking about performence because you avoid copying the things. Blah, blah, blah.
If you need to copy, you should copy. The only reason why its using pointers is because the author didn't want to copy the things when he/she copies the list of things, in other words, he/she wants to maintain the same things in two locations (lists): Ownership sharing, as I said before.
On the other hand, note that the class is called basemesh. So the real point of the pointers here could be to work with polymorphic vertices, edges, etc (Dynamic binding).
NOTE: If performance was the point here, I'm pretty sure the author would be using compact and aligned non-cache-miss-prone std::vector instead of std::list. In this case, the most presumable reason about the use of pointers is polymorphism, not performance. Anything related to pointers, dereferencing, and transversing linked lists will always have less performance than compact data, exactly what std::vector<Vertex> is, for example. Again, if the use of pointers is not for polymorphism, is for ownership related things, not performance.
Other note: Copying Yes, you are copying. But note what and how are copying. Vertices are, except of a very rare implementation, pairs of floats/ints. There is no gain at all about copying 64bits of floats vs 32/64bits of pointers.
Also note that, except you don't be so lucky, you are copying things stored at the same cache line, or almost at the cache.
A good rule about optimization nowadays is: Try to optimize memory accesses, not CPU cicles. I recommend this thread: What is "cache-friendly" code?, and this for a practical case: Why are elementwise additions much faster in separate loops than in a combined loop?. Finally, this thread contains good notes about optimizing using modern compilers.
My guess is that it's either made for a very unusual specific case, but more likely, it's written by a programmer who doesn't know how heap allocations or std::list actually work, and just blindly use pointers.
It seems very unlikely a std::list of pointers to single vertices was the best option performance- or designwise.
On a practical level if a method changes a point it does not need to reproduce the change in the other data structures. They will all point to the same thing.
But in terms of memory management it would be wise to use smart pointers,
At a guess I'd say it's so that these objects can have pointers to each other (e.g. an Edge can have pointers to two Vertices, each of which can have a pointer back to the Edge).
If all the Vertices lived in a std::list in basemesh, then pointers to them would not be reliable, although list::iterators might work well enough.
Using pointers is less efficient when retrieving inner data in general because you will have to dereference the value every time you access it.
But at the same time it will be more efficient when passing data around, since you are just passing pointers. I guess the solution chosen is related to the fact that data is shared between multiple objects by composition. Eg: multiple Edge instances could refer to same Vertex.
Now std::list guarantees that addresses to values contained are consistent until the element itself is removed so actually doing something like
Edge(const Vertex *v1, const Vertex *v2) { .. }
std::list<Vertex>::iterator it = std::advance(vertices.begin(), 3);
std::list<Vertex>::iterator it2 = std::advance(vertices.begin(), 5);
new Edge(&(*it), &(*it2));
Would work since addresses won't be invalidated so there is no real necessity to use pointers to store objects. Actually by using this solution you don't need to care about memory management of single objects since you won't need to delete them or wrap them into smart pointers.
It's using pointers for performance reasons and to reduce the chance of an error.
Imagine the alternative of not using pointers. Every insertion into class basemesh would cause a copy of the object to be created, and every time you access an object, if you aren't careful, you'll get a copy as well.
For example, imagine this statement:
Edge e = m_edges[0];
e.doSomethingThatModifiesState();
In this example, without pointers, you'll have a copy of the object, and any operations you perform on it will not affect the actual edge object stored in m_edges.
With pointers, you don't have this issue:
Edge* e = m_edges[0];
e->doSomethingThatModifiesState();
In this example, no copy of the object is made, and when you do something, you get the intended behavior.
As many others said the speed is the most obvious reason. Another reason is to get polymorphic behavior through pointers to the base class.
See this example.
an University class has a Director and many student So my class will be like this
a)
class University {
Director d;
Student list[1000];
};
or
b)
class University {
Director* d;
Student* list[1000];
};
My problem is how to decide whether class attributes should be pointer or value.
Most all other answers focus on the detail of heap vs. direct containment (or provide no information at all, like use pointers when you want pointers... Rather than focusing on the details, consider the overall design of the application.
The first question would be about ownership. In your program, are those students and director owned by the class? Or do they exist outside of the class scope. In most simple applications, the objects might only exist inside the class, but in other more complex designs, the students might belong to the school, and only be referenced in the class (or the director might also teach some courses to other classes). If the class owns the objects, the composition will be the best approach: hold the director directly as a member, and the students inside a container that is directly held by the class (I would recommend a vector, which is the safe choice for most cases).
If the objects don't belong to the class, then you will rather use aggregation. Whoever owns the object will have to manage the lifetimes and decide how to store the real objects and the class would only hold references (in the general sense) to those objects. Things get more complicated as there are more choices. If ownership can be transferred, then you would dynamically allocate the objects and hold pointers, where you should read smart pointers so that memory will be managed for you.
If ownership does not change and the lifetime of the students/director are guaranteed to extend beyond the lifetime of the class, you could use references. In particular for the director. In the case of the students, it will be more complex as you cannot have containers of plain references, so the solution might still be pointers there, a vector of pointers. Another issue with references is that they cannot be reseated, which means that if you hold a reference to the director, the director of the class will be fixed for the whole lifetime of the class and you won't be able to replace her.
Design is somehow complicated and you will learn with experience, but hopefully this will provide a quick start onto your problem.
The issue here is: Where is the storage for these member variables? Sometimes it makes sense that a piece of data was allocated somewhere else and used other places. In that case a pointer may make sense (rather than using a copy constructor). However, usually that isn't the case (especially with encapsulation). Then you want to store the member data in the class. In such a case, and your example looks like it is, you don't want to use a pointer.
how to decide whether class attributes should be pointer or value
I would mostly go for value (i.e. object). In some special cases, I will choose a pointer (may be a smart one!). For your case, below would suffice:
class University {
Director d;
std::vector<Student> list;
public:
University () { list.reserve(1000); }
};
The advantage of having an object is that you don't have to do your own garbage collection as the resource management will be automatic.
Pointers can be used, when you want to change the ownership of the resource (similar to shallow copy), at the same time avoiding expensive copies created during copy c-tor or assignment. In all other cases, use objects (i.e. value) for composition.
Well it depends. Pointers should be used when you want to add stuff to the heap, while this means you have a bit more freedom in when/how you allocate memory, you have to add more code to avoid memory leaks: ie destructors and deleting stuff. It also allows you to easily modify the values from other functions/classes without having to pass a reference, just pass it in its pointer form.
One obvious situation when pointers are totally needed is in a binary tree node object, since it must contain objects of the same type as itself, it must use pointers to those objects. IE:
struct Node{
Node* left;
Node* right;
//Other stuff
};
In many situations however, its up to your own discretion. Just be responsible for your pointers if you use them.
Actually there are three options
1. Object
2. Reference
3. Pointer
It's part of the design/architect .. on what to use for what object.
Mostly .. the deciding criteria will be, lifecycles of the objects and the containers.
In both cases the class attributes are being stored by value, it just happens that in the second case those values are pointers.
Use pointers when you want pointers, use non-pointers when you don't want pointers. This entirely depends on the desired semantics of the class that you are writing.
This is what i would go for:
class University {
Director d;
Student **list;
};
Even though its much of a personal matter. i think using pointer to pointer is better in this case if you know what you are playing with!
I dont think a pointer array is a good choice. If you dont want pointers then use Value
I'd like to manage a bunch of objects of classes derived from a shared interface class in a common container.
To illustrate the problem, let's say I'm building a game which will contain different actors. Let's call the interface IActor and derive Enemy and Civilian from it.
Now, the idea is to have my game main loop be able to do this:
// somewhere during init
std::vector<IActor> ActorList;
Enemy EvilGuy;
Civilian CoolGuy;
ActorList.push_back(EvilGuy);
ActorList.push_back(CoolGuy);
and
// main loop
while(!done) {
BOOST_FOREACH(IActor CurrentActor, ActorList) {
CurrentActor.Update();
CurrentActor.Draw();
}
}
... or something along those lines. This example obviously won't work but that is pretty much the reason I'm asking here.
I'd like to know: What would be the best, safest, highest-level way to manage those objects in a common heterogeneous container? I know about a variety of approaches (Boost::Any, void*, handler class with boost::shared_ptr, Boost.Pointer Container, dynamic_cast) but I can't decide which would be the way to go here.
Also I'd like to emphasize that I want to stay away as far as possible from manual memory management or nested pointers.
Help much appreciated :).
To solve the problem which you have mentioned, although you are going in right direction, but you are doing it the wrong way. This is what you would need to do
Define a base class (which you are already doing) with virtual functions which would be overridden by derived classes Enemy and Civilian in your case.
You need to choose a proper container with will store your object. You have taken a std::vector<IActor> which is not a good choice because
Firstly when you are adding objects to the vector it is leading to object slicing. This means that only the IActor part of Enemy or Civilian is being stored instead of the whole object.
Secondly you need to call functions depending on the type of the object (virtual functions), which can only happen if you use pointers.
Both of the reason above point to the fact that you need to use a container which can contain pointers, something like std::vector<IActor*> . But a better choice would be to use container of smart pointers which will save you from memory management headaches. You can use any of the smart pointers depending upon your need (but not auto_ptr)
This is what your code would look like
// somewhere during init
std::vector<some_smart_ptr<IActor> > ActorList;
ActorList.push_back(some_smart_ptr(new Enemy()));
ActorList.push_back(some_smart_ptr(new Civilian()));
and
// main loop
while(!done)
{
BOOST_FOREACH(some_smart_ptr<IActor> CurrentActor, ActorList)
{
CurrentActor->Update();
CurrentActor->Draw();
}
}
Which is pretty much similar to your original code except for smart pointers part
My instant reaction is that you should store smart pointers in the container, and make sure the base class defines enough (pure) virtual methods that you never need to dynamic_cast back to the derived class.
As you have guessed you need to store the objects as pointers.
I prefer to use the boost pointer containers (rather than a normal container of smart pointers).
The reason for this is the boost ptr container access the objects as if they were objects (returning references) rather than pointers. This makes it easier to use standard functors and algorithms on the containers.
The disadvantage of smart pointers is that you are sharing ownership.
This is not what you really want. You want ownership to be in a single place (in this case the container).
boost::ptr_vector<IActor> ActorList;
ActorList.push_back(new Enemy());
ActorList.push_back(new Civilian());
and
std::for_each(ActorList.begin(),
ActorList.end(),
std::mem_fun_ref(&IActor::updateDraw));
If you want the container to exclusively own the elements in it, use a Boost pointer container: they're designed for that job. Otherwise, use a container of shared_ptr<IActor> (and of course use them properly, meaning that everyone who needs to share ownership uses shared_ptr).
In both cases, make sure that the destructor of IActor is virtual.
void* requires you to do manual memory management, so that's out. Boost.Any is overkill when the types are related by inheritance - standard polymorphism does the job.
Whether you need dynamic_cast or not is an orthogonal issue - if the users of the container only need the IActor interface, and you either (a) make all the functions of the interface virtual, or else (b) use the non-virtual interface idiom, then you don't need dynamic_cast. If the users of the container know that some of the IActor objects are "really" civilians, and want to make use of things which are in the Civilian interface but not IActor, then you will need casts (or a redesign).