deleting an object

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

deleting an object

Post by short »

Gonna cut out unnecessary code:

Code: Select all

class Particle_Emitter : Object
{
private:
	...
	// member variables
	Particle * s_Particle; // a single particle
        ...
public:

/* ||||||| DESTRUCTOR ||||||||| */
	~Particle_Emitter();
Inside the constructor of Particle_Emitter allocate_memory_particle is called on s_Particle:

Code: Select all

Particle_Emitter::Particle_Emitter(const unsigned int type, const unsigned int density)
{
	.....

	allocate_memory_particle(s_Type);

	init_particles();
}

Code: Select all

void Particle_Emitter::allocate_memory_particle(const unsigned int type)
{
	if(type == CIRCLE)
	{
		Particle * qp = new Particle(0.0f, 2*(float)M_PI);
		s_Particle = qp;
	}
}

Intuitively, I wrote the following destructor for particle_emitter:

Code: Select all

Particle_Emitter::~Particle_Emitter()
{
	delete(s_Particle);
}
Which throws an exception. I understand the idea in general, I've read through Bjarne's book a few times trying to get it and for some reason I'm missing what is going wrong here.
Well, I am allocating a new Particle() and setting s_Particle to point to it. So I thought it made sense that I need to pass that pointer to be freed.

Do any of you guys see where I'm going wrong? (The program has no problems running without the delete line in the destructor, I just didn't want to have a big fat memory leak). Thanks
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: deleting an object

Post by short »

I think editing my original post would make my progression unclear, so I'm posting a reply:

In particle_emitter I wrote the following function like this:

Code: Select all

void Particle_Emitter::deallocate_memory_particle()
{
	delete(s_Particle);
}
In my particle_system update method I have the following:

Code: Select all

void Particle_System::update()
{
	std::vector<Particle_Emitter>::iterator it; // Iterator

	for(it=o_Particle_Container.begin();it < o_Particle_Container.end();)
	{
		if(it->s_flag_onscreen == false && it->get_Repeat() == false)
		{
			// erase returns a pointer to the next object in the STL container
			it->deallocate_memory_particle();
			it = o_Particle_Container.erase(it);
		}
		// we only want to add to it if we don't delete an object, or we will add twice when we delete an object.
		else
		{
			it++;
		}
	}
}
This, seems to do the job. I don't think my misunderstanding is how delete/new works, but when the destructor is called. I know an objects destructor is called when said object goes "out of scope." Since I was using an stl container, the o_Particle_Container was calling the iterators destructor every finite interval, OK.

My question is, is this the best way you guys can see for deleting the allocated memory? Specifically calling a de-allocating method? If so, what's the point of having a destructor in the first place? (in this specific example)
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: deleting an object

Post by dandymcgee »

This:

Code: Select all

Particle_Emitter::~Particle_Emitter()
{
   delete(s_Particle);
}
Should be:

Code: Select all

Particle_Emitter::~Particle_Emitter()
{
   delete s_Particle;
}
And if you do it this way:

Code: Select all

void Particle_Emitter::deallocate_memory_particle()
{
   delete(s_Particle);
}
You should also change delete:

Code: Select all

void Particle_Emitter::deallocate_memory_particle()
{
   delete s_Particle;
}
Some other (unimportant) points:

This:

Code: Select all

void Particle_Emitter::allocate_memory_particle(const unsigned int type)
{
   if(type == CIRCLE)
   {
      Particle * qp = new Particle(0.0f, 2*(float)M_PI);
      s_Particle = qp;
   }
}
Should probably be:

Code: Select all

void Particle_Emitter::allocate_memory_particle(const unsigned int type)
{
   if(type == CIRCLE)
   {
      s_Particle = new Particle(0.0f, 2*(float)M_PI);
   }
}
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: deleting an object

Post by short »

dandymcgee wrote:This:

Code: Select all

Particle_Emitter::~Particle_Emitter()
{
   delete(s_Particle);
}
Should be:

Code: Select all

Particle_Emitter::~Particle_Emitter()
{
   delete s_Particle;
}
What is the difference between the lack of parenthesis?
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
User avatar
Bakkon
Chaos Rift Junior
Chaos Rift Junior
Posts: 384
Joined: Wed May 20, 2009 2:38 pm
Programming Language of Choice: C++
Location: Indiana

Re: deleting an object

Post by Bakkon »

short wrote:What is the difference between the lack of parenthesis?
Just convention, I think. Parenthesis make it look like a function when its an operator. I've never actually seen it used like that before.
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: deleting an object

Post by short »

Bakkon wrote:
short wrote:What is the difference between the lack of parenthesis?
Just convention, I think. Parenthesis make it look like a function when its an operator. I've never actually seen it used like that before.
So removing the parenthesis wouldn't solve the issue, just a convention? And I concur, after looking at the code I agree the parenthesis do make it look like a fn, thanks.
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
qpHalcy0n
Respected Programmer
Respected Programmer
Posts: 387
Joined: Fri Dec 19, 2008 3:33 pm
Location: Dallas
Contact:

Re: deleting an object

Post by qpHalcy0n »

Have you supplied good copy constructors?

You may be pushing a copy somewhere, then when its destroyed you end up with two delete's.
Genesis
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 6
Joined: Mon May 17, 2010 9:01 am

Re: deleting an object

Post by Genesis »

When a particle is deleted during the update() you need to specify that s_Particle no longer contains a valid pointer to object. You can do this using automated memory management with smart pointers (the example below uses std::shared_ptr from C++0x) or by setting the variable to 0 or NULL (or nullptr in C++0x). Setting the pointer to 0 after deleting will prevent invalid deletions of unallocated memory at a later point since delete(0) safely resolves to a no-op.

std::shared_ptr Version

Code: Select all

#include <memory>
class Particle_Emitter : Object
{
private:
	...
	// member variables
	std::shared_ptr<Particle> s_Particle; // a single particle
        ...
public:

/* ||||||| DESTRUCTOR ||||||||| */
	~Particle_Emitter();

Code: Select all

Particle_Emitter::Particle_Emitter(const unsigned int type, const unsigned int density)
{
	.....

	allocate_memory_particle(s_Type);

	init_particles();
}

Code: Select all

void Particle_Emitter::allocate_memory_particle(const unsigned int type)
{
	if(type == CIRCLE)
	{
		std::shared_ptr<Particle> qp(new Particle(0.0f, 2*(float)M_PI));
		s_Particle = qp;
	}
}

Code: Select all

Particle_Emitter::~Particle_Emitter()
{
	// Do Nothing Here Since shared_ptr Deallocates When Reference Count Is Zero
}

Code: Select all

void Particle_Emitter::deallocate_memory_particle()
{
	// Do Nothing Here Since shared_ptr Deallocates When Reference Count Is Zero
}

Code: Select all

void Particle_System::update()
{
	std::vector<Particle_Emitter>::iterator it; // Iterator

	for(it=o_Particle_Container.begin();it < o_Particle_Container.end();)
	{
		if(it->s_flag_onscreen == false && it->get_Repeat() == false)
		{
			// erase returns a pointer to the next object in the STL container
			it->deallocate_memory_particle();
			it = o_Particle_Container.erase(it);
		}
		// we only want to add to it if we don't delete an object, or we will add twice when we delete an object.
		else
		{
			it++;
		}
	}
}
--------------------------------------------------------------------------------------------

Regular Pointer Version

Code: Select all

class Particle_Emitter : Object
{
private:
	...
	// member variables
	Particle *s_Particle; // a single particle
        ...
public:

/* ||||||| DESTRUCTOR ||||||||| */
	~Particle_Emitter();

Code: Select all

Particle_Emitter::Particle_Emitter(const unsigned int type, const unsigned int density)
: s_Particle(0)
{
	.....

	allocate_memory_particle(s_Type);

	init_particles();
}

Code: Select all

void Particle_Emitter::allocate_memory_particle(const unsigned int type)
{
	if(type == CIRCLE)
	{
		Particle *qp = new Particle(0.0f, 2*(float)M_PI);
		s_Particle = qp;
	}
}

Code: Select all

Particle_Emitter::~Particle_Emitter()
{
	if(s_Particle) delete s_Particle;
}

Code: Select all

void Particle_Emitter::deallocate_memory_particle()
{
	if(s_Particle) delete s_Particle;
	s_Particle = 0;
}

Code: Select all

void Particle_System::update()
{
	std::vector<Particle_Emitter>::iterator it; // Iterator

	for(it=o_Particle_Container.begin();it < o_Particle_Container.end();)
	{
		if(it->s_flag_onscreen == false && it->get_Repeat() == false)
		{
			// erase returns a pointer to the next object in the STL container
			it->deallocate_memory_particle();
			it = o_Particle_Container.erase(it);
		}
		// we only want to add to it if we don't delete an object, or we will add twice when we delete an object.
		else
		{
			it++;
		}
	}
}
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: deleting an object

Post by short »

When a particle is deleted during the update() you need to specify that s_Particle no longer contains a valid pointer to object. You can do this using automated memory management with smart pointers (the example below uses std::shared_ptr from C++0x) or by setting the variable to 0 or NULL (or nullptr in C++0x). Setting the pointer to 0 after deleting will prevent invalid deletions of unallocated memory at a later point since delete(0) safely resolves to a no-op.
oh, wow! Thanks !! :] that really cleared things up for me. Yay for learning something new!! :] :]
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: deleting an object

Post by dandymcgee »

short wrote:
Bakkon wrote:
short wrote:What is the difference between the lack of parenthesis?
Just convention, I think. Parenthesis make it look like a function when its an operator. I've never actually seen it used like that before.
So removing the parenthesis wouldn't solve the issue, just a convention? And I concur, after looking at the code I agree the parenthesis do make it look like a fn, thanks.
I had never seen it like that before either (didn't even realize you could put parenthesis there), so I wasn't sure if it was causing a problem or not. Apparently it doesn't make a difference though. :roll:
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
Post Reply