Hi so I've got some nice tree hierarchy of objects in program i'm working on. I've came across a problem with communicating the bottom to top way. How I have it set up right now is that in every constructor I pass a reference to object creating the new object. Simple structure would look like this:
[Controller] -> [World] -> [Object]
Going up one layer (from world to controller or from object to world) is OK. But where the problem starts to occur is when I try to go up 2 layers.
Here is a simplified structure of how I have set it up:
Controller.h:
#include "World.h"
Class Controller {
public:
Controller() {
_worlds.push_back(World(*this));
)
void update() { // Called on a loop from main program loop
_worlds[0].update(); // Calls update of active world, in this case world[0]
}
vector<World> _worlds;
Camera _camera; // class with checkIfInView function
}
World.h:
#Include "Object.h"
Class Controller;
Class World {
World(Controller& ref) : _controller(ref) {
_objects.push_back(Object(*this));
_controller._camera.doStuff(); // works OK
}
void update() {
for (auto& i : _objects)
i.update();
}
vector<Object> _objects;
Controller& _controller;
}
Object.h:
Class World;
Class Object {
Object(World& ref) : _world(ref) {}
void update();
World& _world;
}
Object.cpp:
#include "Controller.h"
#include "World.h"
void Object::update() {
_world._controller._camera.checkIfInView(*this); // Read access violation
}
Controller hold one single camera object which is responsible for what is being shown. What I need is a way for Objects to call checkIfInView to know if they should render or not. Is there any other way to do this or a way to fix it?
EDIT: Updated code.
The problem
Let's look at your nice chain, starting with the Controller constructor. As it's the top object of your hierarchy, it the start of the construction. I imagine that in main() you have something like
Controller c;
This will cause the constructor to be called:
Controller() {
_worlds.push_back(World(*this)); // !!!
}
World(*this) will create a new temporary world that you'll push into the vector of worlds of your controller. The temporary object only exists for the time of the expression in which it appears.
The temporary World will then be constructed with
World(Controller& ref) : _controller(ref) { // ref to controller is kept
_objects.push_back(Object(*this)); // ouch!!!
_controller._camera.doStuff(); // works OK
}
Now an object will be created which refers to *this world. Ouch!! Remember that that world is temporary ? At the end of the construction it will be deleted, so that all objects will refer to a C++ object that no longer exists and hence the UB which happen to produce the segmentation fault in your case.
The start of a solution
The design that you have is quite delicate. Think twice if you couldn't find a safer design pattern. If you want nevertheless to pursue in this direction, avoid creating objects using temporary items: create dynamically allocated ones instead.
Controller() {
_worlds.push_back(*new World(*this)); // !!! risk of leakage
}
The next thing would be to use pointers instead of references:
Controller() {
_worlds.push_back(new World(*this)); // risk of leakage
}
Of course, you'd need to change the rest of the code accordingly, to work with pointers.
The next thing would be to opt for shared pointers: this avoids risk of leakage:
Controller() {
_worlds.push_back(make_shared<World>(*this)); // risk of leakage
}
In the adaptation of your code you'd then need to make a difference between shared_ptr in your vectors, which refers to the object, and weak_ptr to the parten objects, to indicate tha the parent is now shared owned by the child but by another object.
A better solution ?
I warn you that it will not be a piece of cake. As soon as you have pointers, you'd need to take care of the rule of 3 for each class.
Many issues arise from:
1) the nested construction -> may be worth considering the builder design pattern
2) the risk of mixing of static objects and dynamically created objects, never knowing which kind is the parent. -> may be worth using a protected/private constructor and use a factory method for making sure that all objects are always dynamic objects.
Related
TLDR: I think I'm using unique_ptr wrongly, but I'm not sure how to do this otherwise.
I am trying to write a simple physics engine wrapped up in an entity component system. The physics world is essentially the main manager class for all objects that are affected by physics, that should contain all physics properties for entities in the world(ideally stored in a std::vector). In every update loop, after the engine solves constraints, it iterates through the vector of physics objects stored in the physics world and applies the forces, accelerations, impulses etc.
There is also a SceneManager that stores more general entities (eg. for rendering etc) and a SceneEntity which stores behaviour specific components.
I chose to use vector<unique_ptr> for storage because there should only be one instance of each entity (physics or scene) - the end user can handle the raw pointer and pass it to functions etc, but the lifetime of the entities themselves are handled by the SceneManager and PhysicsWorld.
The general structure is as follows:
class PhysicsWorld
{
private:
unique_ptr<PhysicsEntity> entities;
public:
void addEntity(PhysicsEntity * entity)
{
unique_ptr<PhysicsEntity> entity_ptr(entity);
entities.push_back(std::move(entity_ptr));
}
}
class PhysicsEntity
{
private:
unsigned int id;
float gravity;
public:
Entity();
~Entity();
void setGravity(float val);
}
PhysicsWorld world{};
PhysicsEntity * physent = new PhysicsEntity{};
physent->setGravity(3.0f);
world.addEntity(physent)
SceneManager scene{};
RigidbodyComponent * rbcomp = new Rigidbody{ent};
SceneEntity * sceneEnt = new SceneEntity{};
sceneEnt->addComponent(rbcomp);
scene->addEntity(sceneEnt);
My problem is that when I run this code, I get an error from xutility saying "attempting to reference a deleted function" - I believe it occurs somwhere around world.addEntity(). After much searching, I've concluded that this is due to my use of unique_ptr. Is this error occurring because unique_ptr is not the right tool for the job, or am I missing something - or is the error elsewhere?
The issue was that I had not defined move constructors and move assignment operators for PhysicsWorld, so it was using the default ones, which in turn were calling the (deleted) copy constructors for the PhysicsEntity stored in the vector. The code compiled after I defined those.
I have some code:
class LowLevelObject {
public:
void* variable;
};
// internal, can't get access, erase, push. just exists somewhere
std::list<LowLevelObject*> low_level_objects_list;
class HighLevelObject {
public:
LowLevelObject* low_level_object;
};
// my list of objects
std::list<HighLevelObject*> high_level_objects_list;
// some callback which notifies that LowLevelObject* added to low_level_objects_list.
void CallbackAttachLowLevelObject(LowLevelObject* low_level_object) {
HighLevelObject* high_level_object = new HighLevelObject;
high_level_object->low_level_object = low_level_object;
low_level_object->variable = high_level_object;
high_level_objects_list.push_back(high_level_object);
}
void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
// how to delete my HighLevelObject* from high_level_objects_list?
// HighLevelObject* address in field `variable` of LowLevelObject.
}
I have low level object which defined in library, it contains field variable for using by user.
I set to this varaible pointer to my HighLevelObject from my code.
I can set callbacks on add and remove LowLevelObject from list in library.
But how can I remove my HighLevelObject from my list of objects?
Of course, I know that I can iterate whole list and find by object by pointer and remove, but it's long way.
List may contains a lot of objects.
Thanks in advance!
The setup lends itself to finding a solution where converting a pointer to an iterator is a constant-time operation. Boost.Intrusive offers this feature. This will require changes to your code though; if you were not careful about encapsulation, these changes might be significant. A boost::intrusive::list is functionally similar to a std::list, but requires some changes to your data structure. This option might not be for everyone.
Another feature of Boost.Intrusive is that sometimes you do not need to explicitly convert a pointer to an iterator. If you enable auto-unlinking, then the actual deletion from the list happens behind the scenes in a destructor. This is not a good option if you need to get the size of your list in constant time, though. (Nothing in the question indicates that getting the size of the list is needed, so I'll go ahead with this approach.)
If you had a container of objects, I might let you work through the documentation for the intrusive list. However, your use of pointers makes the conversion potentially confusing, so I'll walk through the setup. The setup begins with the following.
#include <boost/intrusive/list.hpp>
// Shorten the needed boost namespace.
namespace bi = boost::intrusive;
Since the list of high-level objects contains pointers, an auxiliary structure is needed. We need what amounts to a pointer that derives from a class provided by Boost. (I will proceed assuming that the objects created in CallbackAttachLowLevelObject() must be destroyed in CallbackDetachLowLevelObject(). Hence, I've changed the raw pointer to a smart pointer.)
#include <memory>
#include <utility>
// The auxiliary structure that will be stored in the high level list:
// The hook supplies the intrusive infrastructure.
// The link_mode enables auto-unlinking.
class ListEntry : public bi::list_base_hook< bi::link_mode<bi::auto_unlink> >
{
public:
// The expected way to construct this.
explicit ListEntry(std::unique_ptr<HighLevelObject> && p) : ptr(std::move(p)) {}
// Another option would be to forward parameters for constructing HighLevelObject,
// and have the constructor call make_unique. I'll leave that as an exercise.
// Make this class look like a pointer to HighLevelObject.
const std::unique_ptr<HighLevelObject> & operator->() const { return ptr; }
HighLevelObject& operator*() const { return *ptr; }
private:
std::unique_ptr<HighLevelObject> ptr;
};
The definition of the list becomes the following. We need to specify non-constant time size() to allow auto-unlinking.
bi::list<ListEntry, bi::constant_time_size<false>> high_level_objects_list;
These changes require some changes to the "attach" callback. I'll present them before going on to the "detach" callback.
// Callback that notifies when LowLevelObject* is added to low_level_objects_list.
void CallbackAttachLowLevelObject(LowLevelObject* low_level_object) {
// Dynamically allocate the entry, in addition to allocating the high level object.
ListEntry * entry = new ListEntry(std::make_unique<HighLevelObject>());
(*entry)->low_level_object = low_level_object; // Double indirection needed here.
low_level_object->variable = entry;
high_level_objects_list.push_back(*entry); // Intentional indirection here!
}
With this prep work, the cleanup is in your destructors, as is appropriate for RAII. Your "detach" just has to initiate the process. One line suffices.
void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
delete static_cast<ListEntry *>(low_level_object->variable);
}
There (appropriately) is not enough context in the question to explain why the high level list is of pointers instead of being of objects. One potential reason is that the high-level object is polymorphic, and the use of pointers avoids slicing. If this is the case (or if there is not a good reason for using pointers), an intrusive list could be designed with less impact on existing code. The caveat here is that changes to HighLevelObject are required.
The initial setup is the same as before.
#include <boost/intrusive/list.hpp>
// Shorten the needed boost namespace.
namespace bi = boost::intrusive;
Next, have HighLevelObject derive from the hook.
class HighLevelObject : public bi::list_base_hook< bi::link_mode<bi::auto_unlink> > {
public:
LowLevelObject* low_level_object;
};
In this situation, the list is of HighLevelObjects, not of pointers, nor of pointer stand-ins.
bi::list<HighLevelObject, bi::constant_time_size<false>> high_level_objects_list;
The "attach" callback reverts to almost what is in the question. The one change to this function is that the object itself is pushed into the list, not a pointer. This is why slicing is not a problem; it's not a copy that is added to the list, but the object itself.
high_level_objects_list.push_back(*high_level_object); // Intentional indirection!
The rest of your code might work as-is. We just need the "detach" callback, which again is a one-liner.
void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
delete static_cast<HighLevelObject *>(low_level_object->variable);
}
This answer is for those who do not want to use – or cannot use – Boost.Intrusive.
As long as modifying HighLevelObject is an option, the object could be told how to remove itself from the list. Add a callback to HighLevelObject and invoke it in its destructor.
#include <functional>
#include <utility>
class HighLevelObject {
public:
LowLevelObject* low_level_object;
// ****** The above is from the question. The below is new. ******
// Have the destructor invoke the callback.
~HighLevelObject() { if ( on_delete ) on_delete(); }
// Provide a way to set the callback.
void set_deleter(std::function<void()> && deleter)
{ on_delete = std::move(deleter); }
private:
// Storage for the callback:
std::function<void()> on_delete;
};
Set the callback when an object is added to the high level list.
Caution: This setup supports only one callback. Don't overwrite the callback somewhere else in your code!
Caution: Additional precautions are needed if multiple threads might add elements to high_level_objects_list.
// Callback that notifies when LowLevelObject* is added to low_level_objects_list.
void CallbackAttachLowLevelObject(LowLevelObject* low_level_object) {
HighLevelObject* high_level_object = new HighLevelObject;
high_level_object->low_level_object = low_level_object;
low_level_object->variable = high_level_object;
high_level_objects_list.push_back(high_level_object);
// ****** The above is from the question. The below is new. ******
// Arrange cleanup.
auto iter = high_level_objects_list.end(); // Not thread-safe
high_level_object->set_deleter([iter]() { high_level_objects_list.erase(iter); });
}
With this prep work, the cleanup is in your destructor, as is appropriate for RAII. Your "detach" just has to initiate the process. One line suffices.
void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
delete static_cast<HighLevelObject *>(low_level_object->variable);
}
I was thinking of storing an iterator (specifically, iter in the above) in HighLevelObject and having the destructor use that to call erase() instead of going through a lambda. However, I ran into trouble with the declarations, since members of std::list cannot be instantiated with an incomplete element type. It could be done with type erasure, but at that point I preferred using a function object.
I am a beginner to programming and I am trying to find a way to create a dynamic storage of objects of my pigeon class. Here is my code:
class pigeon {
public:
pigeon(std::string nameI);
void outputInfo();
private:
std::string name;
};
The idea is that I want to be able to add a new object, have a place to store its information, then be able to add another object, and so on. I have no idea where to start with this or even what data structure to use, I have no experience storing objects.
As it was already pointed out in the comments, you should preferably use a container that handles its resources following the RAII/RDID-idiom ( "Resource Acquisition Is Initialisation" / "Resource Destruction is Deletion") so you don't have to worry about it yourself. This is also a simple way of preventing resource leaks when an exception is thrown.
One of the commonly used containers of the C++ standard library is std::vector<>.
You'd use it like this (just to give you an initial idea, please refer to the documentation for further explanation and examples):
#include <vector>
// ...
{
std::vector<pigeon> pigeons;
pigeons.push_back("Karl"); // add three pigeons
pigeons.push_back("Franz"); // at the end of the
pigeons.push_back("Xaver"); // vector
pigeons[1]; // access "Franz"
for(auto /* maybe const */ &p : pigeons) { // iterate over the vector
// do something with pigeon p
}
} // pigeons goes out of scope, its destructor is called which
// takes care of deallocating the memory used by the vector.
Make vector with pointer of your class:
std::vector<pigeon*> pigeons;
Then allocate new pigeon object and push it into your vector:
pigeon * pig = new pigeon("pigeon");
pigeons.push_back(pig);
Rolling my own GUI library for a side-project. Refactoring to use smart pointers; however, I ran into an issue.
I'm aware that you do not want to to use smart pointers across DLL boundaries for obvious reasons. But I feel dirty using 'new' in application code. See below:
// MYFINANCEAPP.H
class MyFinanceApp : public Application
{
MyFinanceApp() : mMainWindow(make_unique<Window>())
{
mMainWindow->AddControl(*(new Button("testButton")));
}
private:
std::unique_ptr<Window> mMainWindow;
};
// WINDOW.H
class Window
{
public:
void AddControl(Control& control) //QUESTION: HOW DO I GET SMART POINTER HERE???
{
mControls.emplace_back(&control)
}
private:
std::vector<std::unique_ptr<Control>> mControls; //Want to use smart pointers so I am not responsible for managing...
};
Am I better to use C++98 style and semantics and handle it myself. Obviously I do not want to pass smart pointers across the interface boundary (i.e. AddControl), but I don't want to be responsible for handling the lifetime of the controls.
Additionally, I feel really dirty using new Button("testButton").
A reminder that ABI issues can be circumvented if you simply make a guarantee that you won't release a DLL compiled on a different compiler/version/platform than the primary executable.
At any rate, regarding your interface design:
void AddControl(Control& control) {
mControls.emplace_back(&control)
}
You've got a problem here, because
Control is Polymorphic (or at least seems to be based on what code you provided) which means you have to pass by reference or by pointer to get a "complete" object, but
You don't want to expose an interface where the user has to maintain raw pointers, even briefly, before passing them along to your application.
This is how I would design around this problem:
class Window {
public:
void AddControl(std::unique_ptr<Control> control) {//Note we're passing by value!
mControls.emplace_back(std::move(control));
}
private:
std::vector<std::unique_ptr<Control>> mControls;
};
Then, in your application:
class MyFinanceApp : public Application {
public:
MyFinanceApp() : mMainWindow(make_unique<Window>()) {
mMainWindow->AddControl(std::make_unique<Button>("testButton"));
}
private:
std::unique_ptr<Window> mMainWindow;
};
Note that this doesn't necessarily stop your users from doing something stupid, like
std::unique_ptr<Window> window_ptr = std::make_Unique<Window>();
Button * button = new Button("This won't be properly deleted!");
window_ptr->AddControl(std::unique_ptr<Button>{button});
delete button; //Whoops!
... But there wasn't necessarily anything stopping them from doing that in the first place.
An alternative is to have a "Factory" associated with the Controls. We'd first need to make a modification to AddControl:
Control & AddControl(std::unique_ptr<Control> control) {
mControls.emplace_back(std::move(control));
return *mControls.back();
}
struct ControlFactory {
static Button & create_button(Window & window, std::string button_text) {
std::unique_ptr<Button> button_ptr = std::make_unique<Button>(button_text);
Button & ref = *button_ptr;
window.AddControl(std::move(button_ptr));
//ref will NOT be invalidated, because the object will still exist in memory,
//in the same location in memory as before. Only the unique_ptr will have changed.
return ref;
}
};
And then you'd simply need to change the access modifiers on all your Control subclasses to not allow direct access to their constructors by end-user programmers. Something like this would probably suffice:
class Button : public Control {
/*...*/
protected:
Button() {/*...*/}
Button(std::string text) {/*...*/}
friend class ControlFactory; //Allows ControlFactory to access, even though access is protected.
};
Then your users would be storing references on their end, which is safer than pointers, though it does mean you need to guarantee that those references never outlive the application itself.
I'm not quite sure that I need an object pool, yet it seems the most viable solution, but has some un-wanted cons associated with it. I am making a game, where entities are stored within an object pool. These entities are not allocated directly with new, instead a std::deque handles the memory for them.
This is what my object pool more or less looks like:
struct Pool
{
Pool()
: _pool(DEFAULT_SIZE)
{}
Entity* create()
{
if(!_destroyedEntitiesIndicies.empty())
{
_nextIndex = _destroyedEntitiesIndicies.front();
_destroyedEntitiesIndicies.pop();
}
Entity* entity = &_pool[_nextIndex];
entity->id = _nextIndex;
return entity;
}
void destroy(Entity* x)
{
_destroyedEntitiesIndicies.emplace(x->id);
x->id = 0;
}
private:
std::deque<Entity> _pool;
std::queue<int> _destroyedEntitiesIndicies;
int _nextIndex = 0;
};
If I destroy an entity, it's ID will be added to the _destroyedEntitiesIndicies queue, which will make it so that the ID will be re-used, and lastly it's ID will be set to 0. Now the only pitfall to this is, if I destroy an entity and then immediately create a new one, the Entity that was previously destroyed will be updated to be the same entity that was just created.
i.e.
Entity* object1 = pool.create(); // create an object
pool.destroy(object1); // destroy it
Entity* object2 = pool.create(); // create another object
// now object1 will be the same as object2
std::cout << (object1 == object2) << '\n'; // this will print out 1
This doesn't seem right to me. How do I avoid this? Obviously the above will probably not happen (as I'll delay object destruction until the next frame). But this may cause some disturbance whilst saving entity states to a file, or something along those lines.
EDIT:
Let's say I did NULL entities to destroy them. What if I was able to get an Entity from the pool, or store a copy of a pointer to the actual entity? How would I NULL all the other duplicate entities when destroyed?
i.e.
Pool pool;
Entity* entity = pool.create();
Entity* theSameEntity = pool.get(entity->getId());
pool.destroy(entity);
// now entity == nullptr, but theSameEntity still points to the original entity
If you want an Entity instance only to be reachable via create, you will have to hide the get function (which did not exist in your original code anyway :) ).
I think adding this kind of security to your game is quite a bit of an overkill but if you really need a mechanism to control access to certain parts in memory, I would consider returning something like a handle or a weak pointer instead of a raw pointer. This weak pointer would contain an index on a vector/map (that you store somewhere unreachable to anything but that weak pointer), which in turn contains the actual Entity pointer, and a small hash value indicating whether the weak pointer is still valid or not.
Here's a bit of code so you see what I mean:
struct WeakEntityPtr; // Forward declaration.
struct WeakRefIndex { unsigned int m_index; unsigned int m_hash; }; // Small helper struct.
class Entity {
friend struct WeakEntityPtr;
private:
static std::vector< Entity* > s_weakTable( 100 );
static std::vector< char > s_hashTable( 100 );
static WeakRefIndex findFreeWeakRefIndex(); // find next free index and change the hash value in the hashTable at that index
struct WeakEntityPtr {
private:
WeakRefIndex m_refIndex;
public:
inline Entity* get() {
Entity* result = nullptr;
// Check if the weak pointer is still valid by comparing the hash values.
if ( m_refIndex.m_hash == Entity::s_hashTable[ m_refIndex.m_index ] )
{
result = WeakReferenced< T >::s_weakTable[ m_refIndex.m_index ];
}
return result;
}
}
This is not a complete example though (you will have to take care of proper (copy) constructors, assignment operations etc etc...) but it should give you the idea what I am talking about.
However, I want to stress that I still think a simple pool is sufficient for what you are trying to do in that context. You will have to make the rest of your code to play nicely with the entities so they don't reuse objects that they're not supposed to reuse, but I think that is easier done and can be maintained more clearly than the whole handle/weak pointer story above.
This question seems to have various parts. Let's see:
(...) If I destroy an entity and then immediately create a new one,
the Entity that was previously destroyed will be updated to be the
same entity that was just created. This doesn't seem right to me. How
do I avoid this?
You could modify this method:
void destroy(Entity* x)
{
_destroyedEntitiesIndicies.emplace(x->id);
x->id = 0;
}
To be:
void destroy(Entity *&x)
{
_destroyedEntitiesIndicies.emplace(x->id);
x->id = 0;
x = NULL;
}
This way, you will avoid the specific problem you are experiencing. However, it won't solve the whole problem, you can always have copies which are not going to be updated to NULL.
Another way is yo use auto_ptr<> (in C++'98, unique_ptr<> in C++-11), which guarantee that their inner pointer will be set to NULL when released. If you combine this with the overloading of operators new and delete in your Entity class (see below), you can have a quite powerful mechanism. There are some variations, such as shared_ptr<>, in the new version of the standard, C++-11, which can be also useful to you. Your specific example:
auto_ptr<Entity> object1( new Entity ); // calls pool.create()
object1.release(); // calls pool.destroy, if needed
auto_ptr<Entity> object2( new Entity ); // create another object
// now object1 will NOT be the same as object2
std::cout << (object1.get() == object2.get()) << '\n'; // this will print out 0
You have various possible sources of information, such as the cplusplus.com, wikipedia, and a very interesting article from Herb Shutter.
Alternatives to an Object Pool?
Object pools are created in order to avoid continuous memory manipulation, which is expensive, in those situations in which the maximum number of objects is known. There are not alternatives to an object pool that I can think of for your case, I think you are trying the correct design. However, If you have a lot of creations and destructions, maybe the best approach is not an object pool. It is impossible to say without experimenting, and measuring times.
About the implementation, there are various options.
In the first place, it is not clear whether you're experiencing performance advantages by avoiding memory allocation, since you are using _destroyedEntitiesIndicies (you are anyway potentially allocating memory each time you destroy an object). You'll have to experiment with your code if this is giving you enough performance gain in contrast to plain allocation. You can try to remove _destroyedEntitiesIndicies altogether, and try to find an empty slot only when you are running out of them (_nextIndice >= DEFAULT_SIZE ). Another thing to try is discard the memory wasted in those free slots and allocate another chunk (DEFAULT_SIZE) instead.
Again, it all depends of the real use you are experiencing. The only way to find out is experimenting and measuring.
Finally, remember that you can modify class Entity in order to transparently support the object pool or not. A benefit of this is that you can experiment whether it is a really better approach or not.
class Entity {
public:
// more things...
void * operator new(size_t size)
{
return pool.create();
}
void operator delete(void * entity)
{
}
private:
Pool pool;
};
Hope this helps.