Entity deletion not working as intended - c++

I'm trying to write an Entity Component System that will let me use a manager class to create and delete Entity classes at will, without having to worry too much about memory management after completion.
It looks something like this:
class Entity {
int testInt = 0;
public:
Test(int a) {
testInt = a;
}
int getTestInt() { return testInt; }
}
class EntityManager {
public:
inline static std::vector< std::unique_ptr<Entity> > EntityVector = {};
static Entity& createEntity(int a) {
auto* e = new Entity(a);
EntityVector.push_back(std::unique_ptr<Entity>(e));
return *e;
}
// should delete an entity through erasing its unique_ptr
// by comparing the testInt value to the given argument
static void destroyEntity(int a) {
EntityVector.erase(
std::remove_if(
EntityVector.begin(),
EntityVector.end(),
[a] (const std::unique_ptr<Entity> &currentEntity) -> bool {
return currentEntity->getTestInt() == a;
}),
EntityVector.end()
);
}
};
The whole thing is larger, but this part produces the issue.
Now when I create an Entity with the EntityManager::createEntity() everything works fine, but when I go to delete the Entity either manually through delete or through the destroyEntity function I wrote, it does not seem to get deleted, even though to my knowledge, deleting a unique_ptr calls the destructor of the object it is pointing to. But I can still access the Entity after. Here is an example:
int a = 5;
Entity testEntity = TestManager::createEntity(a);
// works as expected, outputs 5
std::cout << testEntity.getTestInt() << std::endl;
// does not appear to properly destroy the entity
TestManager::destroyEntity(5); // same thing happens with a passed as an argument
// still prints 5
std::cout << testEntity.getTest() << std::endl;
Which outputs
5
5
My question is: Why does the deletion of the std::unique_ptr<Entity> not actually delete the Entity it is pointing to?

Related

C++ How to store a unique pointer in a stack, and allow objects to take the pointer out of the stack (and also gain ownership)

I am struggling with a failed unit test and cannot fix the problem.
I have an interface class "ContextObject", and a class "Context" that wraps a stack of unique pointers to "ContextObjects". For the test, I also have an implementation "FooContextObject" of the interface class. Shown Below:
struct ContextObject {
virtual ~ContextObject() = 0;
};
ContextObject::~ContextObject() {}
struct FooContextObject : ContextObject {
std::string name;
FooContextObject(const std::string& name) : name(name) {}
virtual ~FooContextObject() {}
};
The Context class is defined as follows:
struct Context {
std::stack<std::unique_ptr<ContextObject>> stack;
void push(std::unique_ptr<ContextObject>&& t) { stack.push(std::move(t)); }
std::unique_ptr<ContextObject> pop() {
if(stack.empty()) {
std::cerr << "Empty stack" << std::endl;
exit(-4);
}
std::unique_ptr<ContextObject> ptr = std::move(stack.top());
stack.pop();
return std::move(ptr);
}
std::unique_ptr<ContextObject>& peak() { return stack.top(); }
};
And my test is:
void addToContext(Context& ctx) {
auto obj = std::make_unique<FooContextObject>("foo");
ctx.push(std::move(obj));
}
void useContextObject(Context& ctx) {
ContextObject* a = ctx.pop().get();
auto b = dynamic_cast<FooContextObject*>(a);
std::cout << b->name << std::endl;
}
int main() {
Context ctx;
addToContext(ctx);
useContextObject(ctx);
}
Can anybody let me know where I am going wrong, and help me get the code to pass the test? Thanks.
ContextObject* a = ctx.pop().get()
Here ctx.pop() returns a unique_ptr which gets destroyed at the end of the expression because it has no owner. You should assign jt to a unique_ptr to keep ownership. Otherwise, you get a dangling pointer and b->name dereferences It, causing undefined behavior
Off topic note: consider changing the signature of push to
void push(std::unique_ptr<ContextObject> t)
This way it is clear to the user of the API that the object passed to push is moved-from

std::find return a class that I can't acesses functions

I come from C/C# language and now I'm trying to learn about C++ and his standards functions.
Now, I'm creating a class called IMonsterDead. I will have a std::vector<IMonsterDead*> with N monsters.
Example:
class IMonsterDead {
public:
IMonsterDead(int Id)
{
this->_Id = Id;
}
virtual void OnDead() = 0;
int Id() const {
return _Id;
}
private:
int _Id;
};
One class which implements that class:
class MonsterTest : public IMonsterDead {
public:
MonsterTest(int generId)
: IMonsterDead(generId)
{
}
virtual void OnDead()
{
std::cout << "MonsterTesd died" << std::endl;
}
};
Ok, if I access directly everything works fine. But I'm trying to use std::find.
Full program test:
int main()
{
std::vector<IMonsterDead*> monsters;
for (int i = 0; i < 1000; i++)
{
monsters.emplace_back(new MonsterTest(1000 + i));
}
int id = 1033;
std::vector<IMonsterDead*>::iterator result = std::find(monsters.begin(), monsters.end(), [id]( IMonsterDead const* l) {
return l->Id() == id;
});
if (result == monsters.end())
std::cout << "Not found" << std::endl;
else
{
// Here I want to access OnDead function from result
}
return 0;
}
So I need to access OnDead function from result but I can't. Intellisense doesn't show anything for me. The result exists.
How can I access that function? Have another better way to do that?
You need to use std::find_if() instead of std::find(). std::find() is for finding an element with a specific value, so you have to pass it the actual value to find, not a user_defined predicate. std::find_if() is for finding an element based on a predicate.
Either way, if a match is found, dereferencing the returned iterator will give you a IMonsterDead* pointer (more accurately, it will give you a IMonsterDead*& reference-to-pointer). You need to then dereference that pointer in order to access any members, like OnDead().
You are also leaking memory. You are not delete'ing the objects you new. And when dealing with polymorphic types that get deleted via a pointer to a base class, the base class needs a virtual destructor to ensure all derived destructors get called properly.
With that said, you are clearly using C++11 or later (by the fact that you are using vector::emplace_back()), so you should use C++11 features to help you manage your code better:
You should use std::unique_ptr to wrap your monster objects so you don't need to delete them manually.
You should always use the override keyword when overriding a virtual method, to ensure you override it properly. The compiler can catch more syntax errors when using override than without it.
You should use auto whenever you declare a variable that the compiler can deduce its type for you. Especially useful when dealing with templated code.
Try something more like this:
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
class IMonsterDead {
public:
IMonsterDead(int Id)
: m_Id(Id)
{
}
virtual ~IMonsterDead() {}
virtual void OnDead() = 0;
int Id() const {
return m_Id;
}
private:
int m_Id;
};
class MonsterTest : public IMonsterDead {
public:
MonsterTest(int generId)
: IMonsterDead(generId)
{
}
void OnDead() override
{
std::cout << "MonsterTest died" << std::endl;
}
};
int main()
{
std::vector<std::unique_ptr<IMonsterDead>> monsters;
for (int i = 0; i < 1000; i++)
{
// using emplace_back() with a raw pointer risks leaking memory
// if the emplacement fails, so push a fully-constructed
// std::unique_ptr instead, to maintain ownership at all times...
monsters.push_back(std::unique_ptr<IMonsterDead>(new MonsterTest(1000 + i)));
// or:
// std::unique_ptr<IMonsterDead> monster(new MonsterTest(1000 + i));
// monsters.push_back(std::move(monster));
// or, if you are using C++14 or later:
// monsters.push_back(std::make_unique<MonsterTest>(1000 + i));
}
int id = 1033;
auto result = std::find_if(monsters.begin(), monsters.end(),
[id](decltype(monsters)::value_type &l) // or: (decltype(*monsters.begin()) l)
{
return (l->Id() == id);
}
// or, if you are using C++14 or later:
// [id](auto &l) { return (l->Id() == id); }
);
if (result == monsters.end())
std::cout << "Not found" << std::endl;
else
{
auto &monster = *result; // monster is 'std::unique_ptr<IMonsterDead>&'
monster->OnDead();
}
return 0;
}
Iterators are an interesting abstraction, in this case to be reduced to pointers.
Either you receive the pointer to the element or you get an invalid end.
You can use it as a pointer: (*result)->func();
You can also use it to create a new variable:
IMonsterDead &m = **result;
m.func();
This should give the same assembly, both possible.

Constructor to add every instance of a class to a list object

New to c++ and OOP. I'm trying to figure out lists and iteration, so I've created the following example code. I create a couple Thing objects, but I want to make sure that when a Thing is created, its constructor adds it to a list "things" (inside the lists object) so that I can keep track of every instance of Thing. At the bottom of main() I then iterate through the list of Things. Is there a better way to do this, or could you point out how to do this in my Thing constructor? Thanks!!
#include <iostream>
#include <list>
class Thing;
class Lists
{
public:
std::list<Thing> things;
Lists() {
std::cout << "List object with list 'things' created" << std::endl;
}
};
class Thing
{
public:
int howMuch, pointer;
Thing(int x, Lists* y)
{
howMuch = x;
y->things.push_back(this);
}
};
int main()
{
//create the object that holds the list of things
Lists lists;
//make some objects, and pass a pointer of the lists to the constructor
Thing thingA(123, &lists);
Thing thingB(456, &lists);
for (std::list<Thing>::iterator it = lists.things.begin(); it != lists.things.end(); ++it)
std::cout << "test" << it->howMuch << std::endl;
return 0;
}
You can store created items inside the Thing class itself using a static field _things:
#include <iostream>
#include <list>
class Thing
{
static std::list<Thing> _things;
public:
int howMuch, pointer;
Thing(int x) : howMuch(x)
{
_things.push_back(*this);
}
static std::list<Thing> getAllThings()
{
return _things;
}
};
std::list<Thing> Thing::_things;
int main()
{
Thing thingA(123);
Thing thingB(456);
auto allThings = Thing::getAllThings();
for (auto it = allThings.begin(); it != allThings.end(); ++it)
std::cout << "test " << it->howMuch << std::endl;
return 0;
}
The original example and the example in answer 1 encounter problems as soon as any Thing is destroyed (as François Andrieux mentioned), even if you use a pointer to Thing in the list. If you use a Thing in a subroutine as a local variable, the Thing is destroyed at the end of this function, but is still in the list. To solve this problem, you have to remove the Thing from the list in the destructor of Thing. But if you do so, you get a problem, when Thing is a global object. You have two global objects - the list and the Thing. It is not clear, which is destroyed first, so you can end up whith an access violation, which is difficult to debug, because it happens after exit().
Here is my proposal:
template<class T>
class InstanceIterator{ // Iterator for an InstanceList
public:
InstanceIterator(T*pT)
: pt(pT)
{}
T& operator*(){ return *pt; }
T* operator->(){ return pt; }
InstanceIterator operator++(){
pt=pt->instanceList.pNext;
return *this;
}
int operator!=(const InstanceIterator<T>& i){ return i.pt!=pt; }
private:
T*pt;
};
template<class T>
class InstanceList{
// this class means not the whole list, but only the element (pNext)
// which is inserted into the object you want to have in a list.
// there is no explizite list, every instance class T has a part of the list
public:
InstanceList(){};
void insert(T* pt){ // gets the this-pointer of the surrounding class
pNext=pFirst;
pFirst=pt;
}
~InstanceList();
static InstanceIterator<T> begin(){ return pFirst; }
static InstanceIterator<T> end(){ return 0; }
static bool empty(){ return pFirst==0; }
private:
InstanceList(const InstanceList&);// no copy constructor
void operator=(const InstanceList&);// no assignment
static T* pFirst;
T* pNext;
friend class InstanceIterator<T>;
};
template<class T>
InstanceList<T>::~InstanceList(){
T**ppInst=&pFirst;
// search for myself
while(&((*ppInst)->instanceList)!=this) { // its me?
if(0==(*ppInst)) {
return; // emergency exit
}
ppInst=&((*ppInst)->instanceList.pNext); // the next please
}
// and remove me from the list
(*ppInst)=pNext;
}
template<class T>
T* InstanceList<T>::pFirst=0;
// how to use and test the above template:
// (uses 3 objects: one is global, one is local,
// and one is deleted before going through the list)
class InstanceTest { // example class, the instances of this class are listed
public:
InstanceTest(int i)
: i(i)
{
instanceList.insert(this); // dont forget this line
}
InstanceList<InstanceTest> instanceList; // must have this line with exact this name
int i;
};
InstanceTest t1(1); // a global object
int main() {
std::cout << "testing InstanceIterator";
InstanceTest t2(2); // a local object
InstanceTest* pt3 = new InstanceTest(3); // will be deleted later
int sum(0);
for(InstanceIterator<InstanceTest> it= InstanceList<InstanceTest>::begin(); it!= InstanceList<InstanceTest>::end();++it){
sum += it->i;
}
int testFailed(0);
if (sum != 6) testFailed++;
delete pt3;
sum = 0;
for (InstanceIterator<InstanceTest> it = InstanceList<InstanceTest>::begin(); it != InstanceList<InstanceTest>::end(); ++it) {
sum += it->i;
}
if (sum != 3) testFailed++;
if (testFailed) {
std::cout << "... FAILED !!!\n";
}
else std::cout << "... OK\n";
return testFailed;
}

copy constructor with template class not getting called

I was trying to write a sample code for implementing shared pointer [just for practice].
In this following example,
why compiler is not complaining about modifying other_T
And why copy constructor SharedPtr(const T& other_T) is not getting called ?
Here is the code snippet.
#include <iostream>
using namespace std;
#define DBG cout<<"[DEBUG]"<<__PRETTY_FUNCTION__<<endl
class RefCount
{
protected:
int m_ref;
RefCount(){ DBG; m_ref = 1 ; }
void reference(){ DBG; ++m_ref; }
void dereference(){ DBG;--m_ref; }
};
template <class T>
class SharedPtr : public RefCount
{
T* m_T;
public:
SharedPtr() { DBG; m_T = new T; }
SharedPtr(const T& other_T){
DBG;
m_T = other_T.m_T;
other_T.dereference();
other_T.m_T = NULL;
}
~SharedPtr() {
DBG;
dereference();
cout<<m_ref<<endl;
if(m_ref <= 0 && m_T != NULL ){
cout<<"Destroying"<<endl;
delete m_T;
m_T = NULL;
}
}
};
class A{};
int main()
{
SharedPtr<A> obj;
cout<<"assigning "<<endl;
SharedPtr<A> obj2 = obj;
cout<<"END"<<endl;
return 0;
}
and the result is segfault.
Your primary problem is that the copy constructor is being called--but you haven't defined a copy constructor, so you're getting the copy constructor that's defined by the compiler by default.
That copy constructor just does a member-wise copy. That means you've allocated one A with new, then pointed two SharedPtr objects at that same A. The first one to get destroyed deletes the A object. Then the second one gets destroyed, attempts to delete the same object again, and havoc ensues.
In the end, it doesn't look to me like much (any?) of this is going to make any real difference though. I'm pretty sure your basic design is broken. To get a working shared pointer, you have one reference count and "raw" pointer to the final object. Then you have N SharedPtr objects referring to that one ref count/pointer structure that in turn refers to the final object.
You're trying to combine the raw pointer/ref count into the individual SharedPtr, and I don't see any way that can actually work.
It also seems to me that the basic concept of what you've called a RefCount is really part of the design of a SharedPtr. As such, I think its definition should be nested inside that of SharedPtr (and probably made private, since the outside world has no reason to know it exists, not to mention being able to access it directly).
With those taken into account, the code might end up something like this:
#include <iostream>
using namespace std;
#define DBG cout<<"[DEBUG]"<<__PRETTY_FUNCTION__<<endl
template <class T>
class SharedPtr {
template <class U>
struct Ref {
mutable int m_ref;
U *data;
Ref(T *data) : m_ref(1), data(data) { DBG; }
void add_ref() const { DBG; ++m_ref; std::cout << "m_ref=" << m_ref << "\n"; }
void sub_ref() const { DBG; --m_ref; std::cout << "m_ref=" << m_ref << "\n"; }
~Ref() { delete data; }
};
Ref<T> *r;
public:
SharedPtr(T *data) { DBG; r = new Ref<T>(data); }
SharedPtr(SharedPtr const &p) : r(p.r) { DBG; r->add_ref(); }
~SharedPtr() {
DBG;
r->sub_ref();
if (0 == r->m_ref) {
delete r;
std::cout << "deleted pointee\n";
}
}
};
class A{};
int main() {
SharedPtr<A> obj(new A);
cout<<"copying "<<endl;
SharedPtr<A> obj2 = obj;
cout<<"END"<<endl;
return 0;
}
Notes: though this fixes at least some of the basic design, it's still quite a ways short of usable. It's missing the dereference operator, so you can't use the pointer to get to the value it points at. It'll break completely in a multi-threaded environment. I haven't thought enough about it to be sure, but my immediate guess is that it's probably not exception safe either.

How to pass a reference of manager to the handler object?

What I want to do is to write a small Manager/Handler class. A Manager distributes and manages Handles. Such a handle could be for example a simple filehandle.
If a consumer wants to get a handle which already exists, the manager simply returns a shared_ptr. If the handle does not exist, the manager creates a new handle and then returns the shared_ptr.
Inside the Manager, those shared_ptr's are stored in a simple STL-Map.
If the last shared_ptr, which was assigned gets deleted, I want my manager to remove the related map-element, so that the handler object automatically gets destructed.
This sounds a bit like garbage-collection(e.g. worker thread, which checks the usage count of the pointers), but I am sure it can be done more elegantly.
How do I pass a reference of the manager instance to the handler object? (e.g. sth. like passing a unique_ptr(this) to the constructor of a new handler)
#include <memory>
#include <iostream>
#include <map>
using namespace std;
/*
* Simple handler class, that actually does nothing.
* This could be e.g. a Filehandler class or sth. like that
*/
class Handler {
private:
int i;
public:
Handler(int i) :i(i) {}
~Handler() {}
// Say who you are.
void print(void) { cout << "I am handler # " << i << endl; }
};
/*
* This is the "manager" class, that manages all handles. A handle is identified
* by an integer value. If a handle already exists, the Manager returns a shared_ptr,
* if it does not exist, the manager creates a new handle.
*/
class Manager {
private:
map<int, shared_ptr<Handler> > handles;
public:
Manager() {}
~Manager() {}
shared_ptr<Handler> get_handler(int identifier) {
shared_ptr<Handler> retval;
auto it = handles.find(identifier);
if(it != handles.end() ) {
retval = it->second;
} else {
retval = shared_ptr<Handler>(new Handler(identifier));
handles.insert( pair<int, shared_ptr<Handler>>(identifier, retval) );
}
return retval;
}
};
int main(int argc, char** argv) {
Manager m;
// Handler 13 doesn't exist, so it gets allocated
auto h = m.get_handler(13);
// Manager knows about handler 13, so it returns the already existing shared_ptr
auto i = m.get_handler(13);
h.reset(); // Well... Let's assume we don't need h any more...
// do some stuff...
i->print();
// ...
i.reset(); // We also loose i. This is exactly the point where i want the manager to forget about the handle 13
return 0;
}
You may want to hold non-owning pointers in your manager to keep track of existing handles, and give away owning shared_ptr with a custom deleter. The custom deleter would make sure the corresponding observing pointer in the manager is removed when the object eventually gets destroyed.
I called this pattern Tracking Factory, and here is how it works. Given an object class (would be Handler in your case):
class object
{
public:
size_t get_id() const
{
return _id;
}
private:
friend class tracking_factory;
object(size_t id) : _id(id) { }
size_t _id = static_cast<size_t>(-1);
};
I define a class which creates instances of object and stores non-owning references (weak_ptrs) to them. This class is the only class through which instances of object can be created - this is why the constructor of object is private, and tracking_factory is declared as friend in order to be able to access it:
class tracking_factory
{
public:
std::shared_ptr<object> get_object(size_t id,
bool createIfNotFound = true)
{
auto i = std::find_if(
begin(_objects),
end(_objects),
[id] (std::pair<size_t const, std::weak_ptr<object>> const& p)
-> bool
{
return (p.first == id);
});
if (i != end(_objects))
{
return i->second.lock();
}
else if (createIfNotFound)
{
return make_object(id);
}
else
{
return std::shared_ptr<object>();
}
}
size_t count_instances() const
{
return _objects.size();
}
private:
std::shared_ptr<object> make_object(size_t id)
{
std::shared_ptr<object> sp(
new object(id),
[this, id] (object* p)
{
_objects.erase(id);
delete p;
});
_objects[id] = sp;
return sp;
}
std::map<size_t, std::weak_ptr<object>> _objects;
};
Then, the rest of program will obtain shared_ptrs to objects through the object_factory: if an object with the desired characteristics (an id member here) has been created already, a shared_ptr to it will be returned without a new object being instantiated. Here is some code to test the functionality:
#include <iostream>
int main()
{
tracking_factory f;
auto print_object_count = [&f] ()
{
std::cout << "Number of objects: " << f.count_instances() << std::endl;
};
print_object_count();
auto p1 = f.get_object(42);
print_object_count();
{
auto p2 = f.get_object(42);
print_object_count();
p1 = f.get_object(0);
print_object_count();
}
print_object_count();
p1.reset();
print_object_count();
}
Finally, here is a live example.
Store std::weak_ptr objects in the map; they don't retain ownership, so when the last std::shared_ptr object goes away the resource will be destroyed. But they do keep track of whether there are any remaining std::shared_ptr objects that point to the original object, so putting them in the map lets you check later whether there is still a resource there.