Creating & deleting pointers

Started by
29 comments, last by Brother Bob 11 years, 8 months ago
If I create a pointer reference in a class:

private:
string* m_pName;
int* m_pHealth;

Animal::Animal(const string& name = "", const int& health = 2)
{
m_pName = new string(name);
m_pHealth = new int(health);
};

Animal::~Animal()
{
delete m_pName;
m_pName = 0;
delete m_pHealth;
m_pHealth = 0;
};

then call this from an external source:

Animal MyAnimal1("Denzel", 12);

Does the object still exist on the HEAP, or do I still need to delete it? This is the bit that confuses me, as if it still exists in memory then surely I still need to get rid of it... don't I?

Any help would be appreciated.
If you get near a point, make it!
Advertisement
[s]You simply can't do that. At the call site you created a couple of temporaries, they're only good for the scope of that function (which in this case is the constructor). By stashing those pointers into the class variables you have not extended the lifetime of the temporaries, all that happens is that when the constructor returns your two member pointers are left pointing to un-allocated memory.[/s]

Edit: Whoops I didn't spot you were creating copies on the heap. Silly me.
So that's a memory leak?!

So do I return a pointer reference to the call of Animal:
*pMyAnimal1 = Animal tempAnimal("Denzel", 12);

then only when I:
delete pMyAnimal1;
and kill dangly pointers:
pMyAnimal1 = 0;

does the memory cease to exist, leaving no floaty memory in the system anymore!
If you get near a point, make it!
There are three different things allocated in your example. A string, an int, and an object (MyAnimal1) of class Animal. The allocation of MyAnimal1, which consists of two pointers, depends on where the declaration is. If the declaration 'Animal MyAnimal1("Denzel", 12);' is in a function, then the object will be allocated on the stack. That also means that it will be deallocated when the function body goes out of scope. That is also when the destructor will be called.

However, if MyAnimal1 is declared as a global parameter, it will be located in the BSS area (pre allocated by the linker). It will not get deallocated until you program terminates.

For the two pointers, the situation is different. The content they point top will always be on the heap. And they will be freed when the destructor is called.

Why are you using a pointer to a string? Why not use the string itself in the class?

You don't need to assign 0 to the pointers in the destructor. The memory will be freed anyway. However, it may be a good practice, helping you to catch errors. Normally, you must not refer to an object that has been destructed, but it is possible if you have a pointer to it. The source code you show above has no such pointer, though.
[size=2]Current project: Ephenation.
[size=2]Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/
You do not have to delete MyAnimal1, it'll be allocated on the stack. The memory for the member variables are allocated on the heap, but the destructor takes care of those. In short, if you don't 'new' a variable you don't have to delete it(generally).

I don't see any reason to use a pointer to a string or integer in this scenario though, I'd change the member variables to non-pointers.

You simply can't do that. At the call site you created a couple of temporaries, they're only good for the scope of that function (which in this case is the constructor). By stashing those pointers into the class variables you have not extended the lifetime of the temporaries, all that happens is that when the constructor returns

your two member pointers are left pointing to un-allocated memory.



This isn't right. The only thing that would be "temporary" is the object MyAnimal1, assuming it's declared in a function. In that case, MyAnimal1 will be created on the stack, but the member variables would be allocated from the heap. When your function ends, the destructor is called, and the member variables are removed from the heap. You don't need to NULL them out.

Please don't up vote something if you don't understand what's being said.

OP, I hope that answers your question.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Thanks for all the help guys, i guess i've learned a lesson on taking advice as well as pointers :D


Why are you using a pointer to a string? Why not use the string itself in the class?


Just trying to get my head around what I can and can't do really, i want to be creating entities with alterable stats later. So I'm trying to understand the correct ways to load and unload them when I get to generating 100+ of them.

One more question if I can, when I do load multiple objects, whats the best method to use. Is it a vector of class objects? Or is there another standard method I'm not aware of?
If you get near a point, make it!

Does the object still exist on the HEAP, or do I still need to delete it? This is the bit that confuses me, as if it still exists in memory then surely I still need to get rid of it... don't I?


MyAnimal1 is created on the stack
The pointers within the class are created on the stack.
The memory that the pointers point to is created on the heap.

Because of the way you have written you destructor all the memory will be released when it is called, so you have done everything right. Especially the redundant nulling of the pointers, its good practice, but might have performance issues in games.

However, I can't see why you are using dynamic memory for this data, why not just let the class members be a string and an int? I apreciate you may have simplified it for the question, in which case ignore this comment.

One more question if I can, when I do load multiple objects, whats the best method to use. Is it a vector of class objects? Or is there another standard method I'm not aware of?

It depends a little on what you want to do. There are a couple of possibilities:

Animal myAnimals[10];

This will allocate space for 10 objects. Again, on the stack if locally in side a function. All 10 objects will have the constructor executed, but with no arguments. Of course, it is better to replace '10' with MAX or something similar.

Animal *myAnimals[10];

This will allocated 10 pointers, initialized to random values. You need to allocate each Animal of your own, and assign it. For example,
myAnimals[0] = new Animal("Denzel", 12);
You will now have to make sure you deallocate each pointer eventually.

Animal *myAnimals = new Animal[10];

This will allocate one space for 10 objects. The advantage compared to the first example is that it will not be deallocated as soon as the declaration goes out of scope. The disadvantage is that you have to deallocate them yourself eventually, doing "delete[] myAnimals;".

std::vector<Animal> myAnimals;

This is maybe the best solution. It will define a vector of Animals, that can be expanded dynamically. It keeps track of the number of elements, which means you don't need a separate counter. It will be deallocated automatically when you go out of scope, so you will not need to do any delete on your own. The variable myAnimals is a "first class object" (compared to arrays in C++ that are handled as pointers). That means you can easily make a copy of it. There is some overhead, but it is very low, so don't worry about performance until you have measurments showing otherwise.

std::unique_ptr<Animal> myAnimal;

This is a smart pointer to one object. So not really about arrays, but nice to know anyway. You can use it with the same syntax as if it was a normal pointer. It has a few interesting attributes: It will be deallocated automatically and it can't be copied elsewhere. It may look like a disadvantage, but that way you can guarantee that there is no danging pointer stashed away somewhere else when the object is deleted.
[size=2]Current project: Ephenation.
[size=2]Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

[quote name='dmatter' timestamp='1343165488' post='4962740']
You simply can't do that. At the call site you created a couple of temporaries, they're only good for the scope of that function (which in this case is the constructor). By stashing those pointers into the class variables you have not extended the lifetime of the temporaries, all that happens is that when the constructor returns your two member pointers are left pointing to un-allocated memory.


This isn't right.[/quote]
Thanks for spotting my mistake BeerNutts! I hadn't noticed that the constructor is actually constructing copies; I misread it as a straight pointer assignment. My bad.

This topic is closed to new replies.

Advertisement