I have a function, that uses information stored in a struct A. This function is called very often and most of the time it can just rely on the information stored in A.
Under some (rare) conditions, one of the objects of A cannot be used. A new object has to be created and it should not live longer than the function (since it can just be used one time and uses lots of storage).
I have a little bit of pseudo code that demonstrates my problem. At the moment I really don't like it, because of the call to "new" but I can't think of another way to accomplish this with smart pointers.
As I read in every book that you should not use pointers directly nowadays and rely on smart pointers, I'm not sure, hot to implement what I want correctly.
struct A{
myData data;
}
void often_called_function(int i, A &structA)
{
// Pointer which shall dynamically point to existing or newly created object
myData *current_data;
// we rarely land here, data can't be used
if (i == 10) {
current_data = new myData(special arguments);
current_data->reinit(i);
}
// most of the time we land here, no need to re-create data, just reinit existing data from struct A
else {
structA.data.reinit(i);
current_data = &structA.data;
}
// do more stuff with current_data
current_data->do_something();
}
So basically I'm looking for a "nicer" and safe way to accomplish this, can anybody help me?
Thanks in advance
You can create a smart pointer to own the new object and free it at the end of the function, but make it empty unless you need to create the new object. When you do create it, just make current_data refer to the object managed by the smart pointer:
void often_called_function(int i, A &structA)
{
// Pointer which shall dynamically point to existing or newly created object
myData *current_data;
// smart pointer that will own the dynamically-created object, if needed:
std::unique_ptr<myData> owner;
// we rarely land here, data can't be used
if (i == 10){
owner = std::make_unique<myData>(special_arguments);
current_data = owner.get();
current_data->reinit(i);
}
// most of the time we land here, no need to re-create data, just reinit existing data from struct A
else{
structA.data.reinit(i);
current_data = &structA.data;
}
// do more stuff with current_data
current_data->do_something();
}
N.B. it looks like you could simplify the function a bit by moving the reinit(i) call out of the conditional branches:
// we rarely land here, data can't be used
if (i == 10){
owner = std::make_unique<myData>(special_arguments);
current_data = owner.get();
}
// most of the time we land here, no need to re-create data, just reinit existing data from struct A
else{
current_data = &structA.data;
}
current_data->reinit(i);
Related
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.
Introduction
I have created a poll data structure for a game engine, as explained in:-
http://experilous.com/1/blog/post/dense-dynamic-arrays-with-stable-handles-part-1
In short, the structure stores values, instead of pointers.
Here is a draft.
template<class T> class Handle{
int id;
}
template<class T> class PackArray{
std::vector <int>indirection ; //promote indirection here
std::vector <T>data;
//... some fields for pooling (for recycling instance of T)
Handle<T> create(){
data.push_back(T());
//.... update indirection ...
return Id( .... index , usually = indirection.size()-1 .... )
}
T* get(Handle<T> id){
return &data[indirection[id.id]];
//the return result is not stable, caller can't hold it very long
}
//... others function e.g. destroy(Id<T>) ...
}
Problem
Most steps of the refactor to adopt this new data structure are simple, e.g.
Bullet* bullet= new Bullet(); //old version
Handle<Bullet> bullet= packBulletArray.create(); //new version
The problem start when it come to some interfaces the require pointer.
As an example, one of the interfaces is the physic engine.
If I want the engine's collision callback, physic engines likes Box2D and Bullet Physics requires me to pass void*.
Bullet* bullet= .... ;
physicBody->setUserData(bullet); <-- It requires void*.
Question: How should I change the second line to a valid code?
Handle<Bullet> bullet = .... ;
physicBody->setUserData( ???? );
Caution:
(1) There is no guarantee that this instance of "Handle" will exist in the future.
physicBody->setUserData( &bullet ); //can't do this
//e.g. "Handle<Bullet> bullet" in the above code is a local variable, it will be deleted soon
(2) There is no guarantee that the underlying object of "bullet" will exist in the same address in the future.
physicBody->setUserData( bullet->get() ); //can't do this
//because "std::vector<T> data" may reallocate in the future
The answer can assume that:
(1) "physicBody" is encapsulated by me already. It can cache generic pointers if requires, but caching a value of Handle is not allowed, because it creates a severe coupling.
(2) "bullet" has a way to access the correct "physicBody" via its encapsulator. "physicBody" is always deleted before "bullet".
(3) "Handle" also cache "PackArray*", this cache is always a correct pointer.
I guess the solution is something about unique-pointer / make_pointer, but I don't have enough experience to use them for this problem.
P.S. I care about performance.
For reference, this is a sequel of a question create dense dynamic array (array of value) as library that has been solved.
I'm making a simple map for simple rogue-like game.
So I need to initialize map with Objects created for each array cell by receiving data from character array[i][j].
Suggested that such CWall, CDoor classes are defined in other files like CWall.cpp, CWall.h, Underneath are the code to initialize in map.cpp
But is this right way to code?
I think this causes a problem of allocating memory.
CObject CMap::insertObject(char character){
if (character = '*') {
CWall cwall;
return cwall;
}
if (character = 'D') {
CDoor cdoor;
return cdoor;
}
if (character = 'F') {
CFood cfood;
return cfood;
}
if (character = 'K') {
CKey ckey;
return ckey;
}
if (character = 'M') {
CMMonster cmmonster;
return cmmonster;
}
if (character = 'm') {
CMonster cmonster;
return cmonster;
}
if (character = '#') {
CPlayer cplayer;
return cplayer;
}
if (character = 'P') {
CPrincess cprincess;
return cprincess;
}
if (character = '&') {
CRock crock;
return crock;
}
if (character = 'S') {
CShield cshield
return cshield;
}
else {
CShield cshield;
return cshield;
}
}
void CMap::initialize(char arr[][COLS]){
for (int i = 0; i <= 11; i++){
for (int j = 0; j <= 38; j++){
char character = arr[i][j];
insertObject(character);
}
}
}
That's not the right way to do it. You are subject to object slicing, since my guess is that your CObject is an object and not a pointer to some object. You need to either return a pointer of type CObject* in your function, then for each case return a new CMonster or new CPlayer etc. Even better, use a smart pointer instead.
What you are trying to implement is called a factory method pattern, see e.g. How to implement the factory method pattern in C++ correctly for more details.
While others correctly pointed out how to code the idea you want coded, I will focus on another thing. Namely, improper usage of polymorphism here. Inheriting everything from meaningless Object smells like Java, and is not welcome in C++. There is simply nothing in common between Princess and Monster (one is kissed, another one is slayed, and to do what with which is up to one's taste), so when both are inherited from Object, it is extremely hard to program the proper game mechanic. You will have to store the actual object type as well (say, an enumeration), and than cast to this type - because only one of them will have method kiss() on them!
The whole code will be a spaghetti of unsafe casts and will be impossible to maintain or reason about.
Instead, go for stongly typed approach. Always know what type is in front of you!
You should be dealing with the data dynamically. What you're doing now has several problems.
A better approach would be:
CObject* CMap::insertObject(char character){
if (character = '*') {
return new CWall();
}
...
This will utilize polymorphism to hide the actual class (such as CWall) behind the generic interface (CObject). As you wrote it, each "new" object, such as cdoor, would actually be passed to a copy constructor for CObject. None of which actually accomplished anything meaningful.
Of course, you need to pair these creations with proper destructions down the road.
Well, for one thing, you aren't actually initializing anything. CWall* cwall = new CWall; would be the proper way to dynamically allocate and initialize a new CWall object (assuming CWall has a default constructor, of course), or any object for that matter.
What you also need to bear in mind is that, for everything you allocate with new, you have to deallocate with delete later. Thus, you will need to put some thought into how you store those allocated objects, so you can ensure your destructor or cleanup function removes all of them when you're done. One design pattern to consider would be the Object Pool, though there are easily several dozen good ways to do it. That's footwork you're going to have to do yourself, though, as only you know enough about your project to select the right design pattern. (That book I linked to is a great resource.)
EDIT: As per your comment, there is one other issue, and that is that you are returning different types of objects. This is a simple issue of inheritance - as long as all of those objects inherit from an abstract base class of CObject (or something similar), you can simply list the return type as CObject*. Then, as long as you're returning an object (or a pointer to an object) that inherits from CObject, you're golden.
EDIT 2: Whenever you use new, you are actually getting a pointer to the dynamically allocated object. That creates some problems of its own, including that new can return a null pointer if the allocation fails. Be sure to check for that! A smart pointer can prevent many of those problems, but your use of smart pointers depends on your design pattern choices.
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.
Hi I am currently in the process of learning QT.
I am using the following code
QStringList list;
list << "item1" << "item2" << "item3" << "item4" << "item5";
ui.listView->setModel(new QStringListModel(list));
Now my understanding is that ui.listView->setModel is being passed as a reference to an object on the heap. Wouldn't this object need to be deleted ? Any suggestions should I be using a boost safe pointer here ? Since every time I update the content of list I would have to call the last statement to update the display.
It is hard to tell from so little code available, but yes you are creating an object on the heap whose address you might lose and so risk a potential memory leak. You should define yourself either a global pointer to the object and delete it when you need a new one.
Even better would be to create a small class containing the reference to the current QStringListModel and define some methods to create a new one, while deleting the old one.
class ListModelHolder {
private:
QStringListModel* model;
public:
ListModelHolder() { model = 0; }
~ListModelHolder() { if(model != 0) delete model; }
set_model(QStringListModel* model) { this->model = model; }
delete_model() { if(this->model) delete this->model; this->model = 0; }
};
Just as an example. You can keep this object at a global scope or as global as you need.
Yes, in that case your should delete new QStringListModel(list), but if you slightly change your code it will be done by your listView:
ui.listView->setModel(new QStringListModel(list, ui.listView));
QListView::setModel does not take ownership of the model nor the selection model, except if the parent of the model is the listview. This because a model can be shared between several different views. It means it is usually up to you to take care of the life othe model and delete it manually.
I recommend that you manage that by yourself, with a pointer to the model in your class. This will also enable you to modify the string list that is used by the model.