Building an index: Copies or pointers? - c++

I have a data structure that stores ... well, data. Now, I need to access various pieces of data in slightly different manner, so I'm essentially building an in-memory index. But I'm wondering: should the index hold pointers or copies?
To elaborate, say I have
class Widget
{
// Ways to access the list of gears...
private:
std::list<Gears> m_gears;
};
Now, I have two Widgets, and there exists between these two a mapping between their Gears. Currently, this is
boost::unordered_map<Gear, Gear>
but Gear is a fairly hefty class, and I feel like making so many copies is poor design. I could store a pointer, but then the mapping is only valid for the lifetime of the corresponding Widgets, and you start getting ->s... (And if that std::list ever changes to a std::vector, it gets more complex...)
Pertaining to the copies, it's actually slightly worse: There's two boost::unordered_maps, one for each direction. So, for each Gear, I'm making up to 2 copies of it.
Alternatively, I could put the index inside the Widget class, but I feel like this violates the responsibilities of the Widget class.

You might try Boost Pointer Container Library: http://www.boost.org/doc/libs/1_43_0/libs/ptr_container/doc/ptr_container.html
I think it addresses exactly the problem you are facing.

Could you store all gears in one place, like statically in the gears class, and then have each mapping AND widget store only the reference/index to it?
You would have to keep track of references to each gear so you know when you can dispose them, but that should be easy enough.

Related

Should I use reference member to deal with dependency between objects?

As a beginner in C++, I am practicing C++ with an algorithm assignment. Along the way, I have some questions that I have difficulty getting through. Pardon me if the questions sound entry-level since I am still learning.
The goal is to find collinear points in a given vector of points with three classes. The following briefly describes the three classes' purposes:
Point: Representing a point with x and y values.
LineSegment: Representing a line segment with two points at ends.
Collinear: Containing the segments found in a vector of Points. The main part of the algorithm.
So, I would expect the client code to look like this:
std::vector<Point> points; // may become huge
// populate points
// ...
Collinear collinear_points(points);
std::vector<LineSegment> segments_in_points = collinear_points.GetSegments();
Since the class Collinear depends on a certain vector of points to get the segments correspondingly, I think it would need it as a data member. The question that keeps haunting me is, should it hold a copy of the vector or hold a raw pointer/reference to the vector outside the object. I think a smart pointer would be an overkill here. According to the old answer here, maybe it is better to go with reference which also avoids potential expensive copying? What is the common practice for this kind of dependency between classes if any exists?
If points gets modified after the construction of collinear_points, then the data collinear_points is referencing will be inconsistent with the segments it contains. Is it common to leave the responsibility to users for making sure the validness of an object depending on other ones? Is there a way to let collinear_points know the content has been modified and put it in an invalid state?
To answer your actual question from the title: A non-owning raw pointer would still be the usual choice, mainly because that’s what we’ve been doing since the old C days. Of course, a pointer has the problem that it can be nullptr. So using a reference communicates more clearly that null is not an allowed value. Because of that I tend to use the reference, although it still feels a tiny bit weird even to myself. But imo it’s the better design decision overall
That said, I believe the real question here is one of ownership. If Collinear does not own the vector, the user of your API has to make sure that the vector lives at least as long as the associated Collinear object. Otherwise you’ll access a dangling pointer/reference and things tend to go downhill from there. ;)
Is there a way to let collinear_points know the content has been modified and put it in an invalid state?
Yes, there is. Own everything. That includes the points vector and the segments vector. Following this approach Collinear could look something like this:
class Collinear {
public:
// usings because I’m a lazy typer
using PointsVec = std::vector<Point>;
using SegmentsVec = std::vector<LineSegment>;
// Take ownership of the points vector by either copying
// or moving it into a member.
explicit Collinear(const PointsVec& p): m_points(p) {}
explicit Collinear(PointsVec&& p): m_points(std::move(p)) {}
// Retain ownership of the segments vector by returning a const ref.
const SegmentsVec& GetSegments(); // Check if you can make it const.
// access functions for the two vectors ...
private:
PointsVec m_points;
SegmentsVec m_segments;
}
Now Collinear controls access to the points vector. You’ll have to write the functions for the permitted operations as members of Collinear. The important thing is never to return a non-const pointer or non-const ref to m_points, because then you might miss write accesses.
The segments vector is similar. Your provide the write access member functions and Collinear retains ownership, which means it can re-calculate it when necessary and the user doesn’t need to be concerned with that. Depending on how expensive the calculation is you can now go wild with lazy evaluation and every optimization you can think of.
There is a completely different design approach, though. Own nothing. Does Collinear have to be a class at all? Could it be a bunch of free functions in a namespace?
namespace Collinear {
std::vector<LineSegment> GetSegments(const std::vector<Point>& points);
}
// ...
auto segments_in_points = Collinear::GetSegments(points);
That’s the opposite of the own-everything approach. Before, you had full control. Now your user has full control. On the other hand, they now have to take care of any laziness/optimizations/update detection.
Which approach is appropriate is a question of a) API design philosophy and b) your conrete situation. What are your users? What do they expect? Which approach makes their lives easier? Since this is an assignment, you probably won’t have any real users. So imagine a group of people that might want to use your code and decide based on that. Or just use the approach you’ll have more fun implementing. The important thing imo: Pick one of the two approaches. Don’t mix them, because such an API is inconsistent. That increases confusion, decreases ease of use, and makes errors more likely.
Btw:
I think a smart pointer would be an overkill here.
Using smart pointers is not a question of overkill. It’s a question of ownership. If you have an owning pointer never use a raw pointer for it. … Unless a legacy API forces you to. Even then it’s a great idea to mark it as owning with a transparent wrapper like gsl::owner<T>.
The question that keeps haunting me is, should it hold a copy of the vector or hold a raw pointer/reference to the vector outside the object
I think you should keep a copy of vector here to keep things generic.You don't want your collinear class depend on a particular vector<Points>, instead it should be like while creating instance of collinear class you just tell it on what vector<Points>, it has to work on.Then if you change this vector and you want collinear also to work on this data set(which you might not want), its your responsibility to tell collinear to work on new data set.If you want collinear to be updated automatically when you update vector<points>, you can do so, but you have to answer questions like what happens to the state of collinear(which would be depending on the vector<points>) when the data set changes.

Object propagation

I have a collection of objects, lets say QVector<ApplicationStates>, which registers the most important operations done in my software. Basically, this object is meant to process redo/undo operations.The application is built using a lot of delegated objects. Operations which have to be registered lie in a lot of these objects. As such, I am always passing my collection of objects, in each delegate under the form:
class AWidget : public QWidget{
AWidget(QVector<ApplicationStates>* states, QWidget* parent = nullptr);
...
It seems ugly to me. I think about two solutions:
Singleton;
Simply declare the QVector as a static global variable (I read that global variables are evil).
Does someone have a suggestion?
Thanks for your answers.
I get into a similar situation from time to time, and I have found simply wrapping your vector in a class called something like "ApplicationContext" then passing a shared pointer or reference to an instance of that around saves the day. It has many benefits:
You avoid the global / singleton, and you are free to in fact have several instances concurrently in the future
If you suddenly have more than just that vector of objects that you need to pass arround, simply extend your context class to add whatever you need
If your vector suddenly becomes a map or changes in other ways, you need not change any interfaces that pass it along such as the signals/slots. (You will need to change the implementation where the vector is used of course).
BONUS: The code becomes easily testable! You can now make test cases for this class.
This might not be the best solution in all cases, but I think it comes pretty close in this case!

Automatically add an object to a vector of that objects parent

I am designing a game engine in c++. I am currently working on categorizing the different entities in the game. My base class is SpriteObject that two classes MovableObject and FixedObject inherit from. Now if i for example create an instance of a MovableObject and want to add it to a Vector of Sprite and a Vector of MovableObject i just do:
Vector<Sprite*> sprites;
Vector<MovableObject*> movableObjects;
MovableObject* movingObject = new MovableObject();
sprites.push_back(movingObject);
movableObjects.push_back(movingObject);
But as the different categories and entities grow the code will get large (and it would get tiresome to add every entity to every vector that it belongs to). How do i automatically add an object to the vector that it belongs to when it is created?
EDIT 1: I think i just came up with a solution, what if i just make a global static class Entities that holds all the vector of entities in the scene. Every entity could have access to this class and when a entity is created it just adds a pointer version of itself to the corresponding vector(s) in that global class.
EDIT 2: But i forgot that my solution requires me to still manually add every entity to its matching vector. I just split the work among the different entities.
This is a nice problem.
I think that I would implement it like this: There will be an addToVector() method in Sprite class, and each derived class will override it to add itself to the corresponding vector.
I would suggest a different approach. But before I start I would like to note one thing with your current design.
I would hide the creation of those objects behind a facade. Call it a scene or whatever. Using new manually is bad from a couple of perspectives. First of all if you decide you want to change the scheme on how you allocate/construct your objects you have to change it everywhere in the code. If you have a lets say a factory like Scene you just change the implementation and the calls to scene->CreateObject<Sprite>() will remain the same everywhere else. This might get important once you start adding stuff like custom memory allocation schemes, object pools etc and at some point you will if you will start to grow your engine. Even if this is just an excercise and a for fun project we all want to do this like its actually done, right ;) ?
Now going back to the core - dont abuse inheritance.
MovableObject is not a Sprite. Static Object is not a sprite either. They are that, movable and static elements.
A sprite can be movable or static, so it has a behavior of a dynamic or static element.
Use composition instead. Make a Sprite accepting behavior, or better a list of behaviors. In fact the Sprite itself is just a behavior on a Game object too, it just controls the way it is presented to the user.
What if you had an object that can be attached multiple behaviors like the fact it is a dynamic one, it has a sprite presence on the scene and even more is a sound emitter!
If you add those behaviors to the object you have to create them first. They can, when constructed, decide to which list they should subscribe to.
This is all metaphors for actually a well known system, that is proven to work well and is actually used in most game engines nowadays. Its a Entity Component System.
You object with behaviors are Entities, Components are those Behaviors and each of them is controlled by one system that knows the component and knows how to update/handle them.
Objects in the scene are merely a set of components attached to them that act upon them.

How to manage millions of game objects with a Slot Map / Object Pool pattern in C++?

I'm developing a game server for a video game called Tibia.
Basically, there can be up to millions of objects, of which there can be up to thousands of deletes and re-creations as players interact with the game world.
The thing is, the original creators used a Slot Map / Object Pool on which pointers are re-used when an object is removed. This is a huge performance boost since there's no need to do much memory reallocation unless needed.
And of course, I'm trying to accomplish that myself, but I've come into one huge problem with my Slot Map:
Here's just a few explanation of how Slot Map works according to a source I found online:
Object class is the base class for every game object, my Slot Map / object Pool is using this Object class to save every allocated object.
Example:
struct TObjectBlock
{
Object Object[36768];
};
The way the slot map works is that, the server first allocates, say, 36768 objects in a list of TObjectBlock and gives them a unique ID ObjectID for each Object which can be re-used in a free object list when the server needs to create a new object.
Example:
Object 1 (ID: 555) is deleted, it's ID 555 is put in a free object ID
list, an Item creation is requested, ID 555 is reused since it's on
the free object list, and there is no need to reallocate another
TObjectBlock in the array for further objects.
My problem: How can I use "Player" "Creature" "Item" "Tile" to support this Slot Map? I don't seem to come up with a solution into this logic problem.
I am using a virtual class to manage all objects:
struct Object
{
uint32_t ObjectID;
int32_t posx;
int32_t posy;
int32_t posz;
};
Then, I'd create the objects themselves:
struct Creature : Object
{
char Name[31];
};
struct Player : Creature
{
};
struct Item : Object
{
uint16_t Attack;
};
struct Tile : Object
{
};
But now if I was to make use of the slot map, I'd have to do something like this:
Object allocatedObject;
allocatedObject.ObjectID = CreateObject(); // Get a free object ID to use
if (allocatedObject.ObjectID != INVALIDOBJECT.ObjectID)
{
Creature* monster = new Creature();
// This doesn't make much sense, since I'd have this creature pointer floating around!
monster.ObjectID = allocatedObject.ObjectID;
}
It pretty much doesn't make much sense to set a whole new object pointer the already allocated object unique ID.
What are my options with this logic?
I believe you have a lot of tangled concepts here, and you need to detangle them to make this work.
First, you are actually defeating the primary purpose of this model. What you showed smells badly of cargo cult programming. You should not be newing objects, at least without overloading, if you are serious about this. You should allocate a single large block of memory for a given object type and draw from that on "allocation" - be it from an overloaded new or creation via a memory manager class. That means you need separate blocks of memory for each object type, not a single "objects" block.
The whole idea is that if you want to avoid allocation-deallocation of actual memory, you need to reuse the memory. To construct an object, you need enough memory to fit it, and your types are not the same length. Only Tile in your example is the same size as Object, so only that could share the same memory (but it shouldn't). None of the other types can be placed in the objects memory because they are longer. You need separate pools for each type.
Second, there should be no bearing of the object ID on how things are stored. There cannot be, once you take the first point into consideration, if the IDs are shared and the memory is not. But it must be pointed out explicitly - the position in a memory block is largely arbitrary and the IDs are not.
Why? Let's say you take object 40, "delete" it, then create a new object 40. Now let's say some buggy part of the program referenced the original ID 40. It goes looking for the original 40, which should error, but instead finds the new 40. You just created an entirely untrackable error. While this can happen with pointers, it is far more likely to happen with IDs, because few systems impose checks on ID usage. A main reason for indirecting access with IDs is to make access safer by making it easy to catch bad usage, so by making IDs reusable, you make them just as unsafe as storing pointers.
The actual model for handling this should look like how the operating system does similar operations (see below the divide for more on that...). That is to say, follow a model like this:
Create some sort of array (like a vector) of the type you want to store - the actual type, not pointers to it. Not Object, which is a generic base, but something like Player.
Size that to the size you expect to need.
Create a stack of size_t (for indexes) and push into it every index in the array. If you created 10 objects, you push 0 1 2 3 4 5 6 7 8 9.
Every time you need an object, pop an index from the stack and use the memory in that cell of the array.
If you run out of indexes, increase the size of the vector and push the newly created indexes.
When you use objects, indirect via the index that was popped.
Essentially, you need a class to manage the memory.
An alternative model would be to directly push pointers into a stack with matching pointer type. There are benefits to that, but it is also harder to debug. The primary benefit to that system is that it can easily be integrated into existing systems; however, most compilers do similar already...
That said, I suggest against this. It seems like a good idea on paper, and on very limited systems it is, but modern operating systems are not "limited systems" by that definition. Virtual memory already resolves the biggest reason to do this, memory fragmentation (which you did not mention). Many compiler allocators will attempt to more or less do what you are trying to do here in the standard library containers by drawing from memory pools, and those are far more manageable to use.
I once implemented a system just like this, but for many good reasons have ditched it in favor of a collection of unordered maps of pointers. I have plans to replace allocators if I discover performance or memory problems associated with this model. This lets me offset the concern of managing memory until testing/optimization, and doesn't require quirky system design at every level to handle abstraction.
When I say "quirky", believe me when I say that there are many more annoyances with the indirection-pool-stack design than I have listed.

Child/Parent structure with different classes in C++

I've decided to make my next game using my own simple engine. I've already written some code for object rendering, physics etc. and now I'm thinking about how to easily connect them together.
I want to make hierarchic structure with one master object, lets call it Scene which will have parent as Sprites or InteractiveObjects and every Sprite or InteractiveObject could have its own child which would have its own child.. I think you already got my point here :)
Let's assume, that every object type will inherit from some base object, let's call it Node for example. I'm not sure yet, if Node will be "real" object which will have its size, position etc. or only abstract wrapper for every object in game (I tend to option two actually).
And finally. My goal is, to have object of actual Scene, call something like Scene->Move(x,y) and it will move every child of Scene (or Sprite, InteractiveObject etc.). Or Scene->Render() and it will render every (renderable) child. If I create Sprite, I want to add child like Sprite->addChild() and child could be another Sprite, InteractiveObject or just simple Node.
And now my question. What's the best way to implement it with C++? Or am I totally wrong and this structure is stupid? :)
I should think that whether or not the structure is sensible depends somewhat on what you really want to achieve -- the system sounds very flexible, but usually there's a trade-off between flexibility and performance. Depending on the genre of the game, performance may be hard enough to come by.
Also, if all things derive from some BaseNode, they all need (although possibly empty) methods for all kinds of things whether or not they actually can be rendered, moved etc. Or you'd end up with lots of dynamic_casts, which isn't very nice either. It might therefore be better to have slightly less flexibility and differentiate between game entities and graphical entities, with the latter being part of the former (you might want to allow a game entity to be made up from multiple graphical entities, or sub-entities, though).
If you do go with your current architecture, I should think that each BaseObject has something like a vector and when you call, say, render() on a master object, it goes through all it's children and calls render on them. They do the same and do any render code that is appropriate to them.
Another question is, though, whether an object could feasibly be attached to several other objects (if there is a difference between rendering and physics, for example). If so, it can get hairy to know when to delete an object, unless you don't use plain BaseObject*, but some form of auto_ptr or shared_ptr.
I hope that this answer does help you a little, though I realise it's not a simple "this is they way!" one.