Hi,

This is a very convoluted problem I spent hours debugging to find that when I call std::vector<object>::push_back(Object()) destructor of previous Object is called.

Is this the behaviour of std::vectors or is something wrong with my code?

#include <iostream>
#include <vector>

class Manager;

class Entity
{
friend class Manager;

private:
	int _mDisplayList; // for opengl, if it matters

public:
	Entity():_mDisplayList(0){};
	~Entity()
	{
		if(_mDisplayList)
		{
			_mDisplayList = 0;
		}
	}
	void render()
	{
		std::cout << _mDisplayList << std::endl;
	}
};

class Manager
{
private:
	std::vector<Entity> _mEntities;
	
public:
	Entity* createEntity()
	{
		// this line invokes ~Entity() of prev Entity();
		_mEntities.push_back(Entity()); 		
		return &(_mEntities.back());
	}
	
	Entity* createEntity(int id)
	{
		Entity* ent = createEntity();
		
		// generate some id for _mDisplayList
		ent->_mDisplayList = id;
		
		return ent;
	}
};

void main()
{
	Manager mgr;
	Entity *ent1, ent2;
	ent1 = mgr.createEntity(1);
	ent2 = mgr.createEntity();
	
	// expect output to be
	// 1
	// 0
	ent1->render();
	ent2->render();
	// but turns out to be
	// <garbage>
	// 0
}

Edited 6 Years Ago by jakesee: n/a

There are quite a few things wrong with your code. The main problem is that you mix classes and class-instances. But to be honest, I think there's a bit of a design issue with your code. You're making it unnecessarily difficult on yourself. Here's a revamped version of your code, which would be a lot closer how I would have designed it:

#include <iostream>
#include <vector>

class Entity
{
private:
    int _mDisplayList; // for opengl, if it matters
public:
    Entity():_mDisplayList(0){};
    Entity(int id):_mDisplayList(id){};
    ~Entity() {}
    void render()
    {
        std::cout << _mDisplayList << std::endl;
    }
};

class Manager
{
private:
    std::vector<Entity*> _mEntities;

public:
    ~Manager() {
        for (unsigned i = 0; i < _mEntities.size(); ++i )
            delete _mEntities.at(i);
    }
    Entity* createEntity(int id = 0)
    {
        Entity * ent = new Entity(id);
        _mEntities.push_back(ent); 		
        return ent;
    }
    void display() {
        std::cout << "Display all entities in manager:\n";
        for (unsigned i = 0; i < _mEntities.size(); ++i )
            _mEntities.at(i)->render();
    }
};

int main()
{
    Manager * mgr = new Manager();
    Entity * ent1, * ent2;

    ent1 = mgr->createEntity(1);
    ent2 = mgr->createEntity();

    ent1->render();
    ent2->render();

    //new
    mgr->display();

    delete mgr;
    std::cin.get();
}

Edited 6 Years Ago by Nick Evan: re-align code

The main problem is that you mix classes and class-instances.

Hi neik_e,

Thanks for the code advice, I think I should really just use std::vector<Entity*> like you suggest.

But can you kindly explain the above qouted point again, I'm not sure If i get you.

Also, getting back to my main question, do you know why the push_back() is calling the destructor of Entity?

Thanks again.

You're using dangling pointers:

Entity* createEntity()
	{
		// this line invokes ~Entity() of prev Entity();
		_mEntities.push_back(Entity()); 		
		return &(_mEntities.back());
	}
	
	Entity* createEntity(int id)
	{
		Entity* ent = createEntity(); // <-- You better think this one through :)

		// generate some id for _mDisplayList
		ent->_mDisplayList = id;
		
		return ent;
	}

Hi,

This is a very convoluted problem I spent hours debugging to find that when I call std::vector<object>::push_back(Object()) destructor of previous Object is called.

Is this the behaviour of std::vectors or is something wrong with my code?

It could be happening due to resizing of the vector. Once the limit of the vector exceeds it would allocate new storage, copy all the previous objects to the new storage and then delete the old one's. Try putting come cout in copy ctor and see it that's what's happening

this is obviously supplement to all the other advice niek_e has given.

Edited 6 Years Ago by Agni: n/a

It could be happening due to resizing of the vector. Once the limit of the vector exceeds it would allocate new storage, copy all the previous objects to the new storage and then delete the old one's. Try putting come cout in copy ctor and see it that's what's happening

Woah! you're a genius! I should have thought of that. I'm a frustrated-turned-happy man now.

finally... thanks to both of you.

EDIT: Just realised I had been such a fool. Don't even know how to use vectors!? =(

Edited 6 Years Ago by jakesee: n/a

This question has already been answered. Start a new discussion instead.