# [C++] Lifetime of Objects Allocated with new

## Recommended Posts

I am writing a program to improve my C++ skills. It currently has a class that can have child classes of the same type (nesting is not limited). I was using array of pointers to store the child classes:
node::~node (void)
{
for (unsigned int i = 0; i < nOfSubs; i++)
delete sub[i];
if (sub) {free (sub); sub = 0;}

if (name) {free (name); name = 0;}
if (cont) {free (cont); cont = 0;}
}
{
sub = (node **) memGet (sub, (nOfSubs + 1) * sizeof (*sub)); //only hand made alloc:malloc (edit: malloc/realloc) switch funtion
if (!sub)
return -1;
sub[nOfSubs] = new node; //note this line!!!
if (sub[nOfSubs]->set (name0, cont0))
{
delete sub[nOfSubs];
if (nOfSubs)
sub = (node **) memGet (sub, nOfSubs * sizeof (*sub));
else
{
free (sub);
sub = 0;
}
return -1;
}
sub[nOfSubs]->sup = this;
nOfSubs++;
return 0;
}


As you can see, I'm using "new" to spawn a new "node". Recently I found this page that suggests that my code should not work, but destructor (node::~node(void)) gets called when I use "delete". Does this work by luck and I'm up to a nasty surprise later or am I misunderstanding the principle of scoping? [Edited by - transistor09 on March 31, 2010 2:35:43 AM]

##### Share on other sites
No, your code looks correct. You delete the objects (not the classes) you new. The destructors of those objects gets invoked at the right time.

##### Share on other sites
A scope is what's between { and }. All the variables created in a scope are destroyed when leaving it, except for those created with the new operator.

So:

{
node n1;
node * n2 = new n2();
} // Here, the n1 destructor will be called, but not n2.

What the page you linked was saying is that when you create an object with new, you must keep its pointer somewhere to be able to call delete on it. For instance, in my example, there's a leak because the pointer on n2 is lost when leaving the scope and there's no way to delete.

I'm not sure to understand everything in the code you provided, but as long as you're creating the object in add and then deleting it in the destructor, it should be fine (unless you keep references to nodes that could be deleted somewhere else in you program).

I'm not sure if my explanation is clear enough.

##### Share on other sites
Oh, right! The variable gets out of scope, not allocated memory! Way to be confusing, Microsoft!

On the other note, will this recursive destructor be a performance killer?

##### Share on other sites
Quote:
 Original post by transistor09Way to be confusing, Microsoft!

What has poor old Microsoft to do with that? XD

##### Share on other sites
Quote:
 Original post by kloffyWhat has poor old Microsoft to do with that? XD

Read the original post and maybe you'll find out...

##### Share on other sites
Quote:
 Original post by FaelenorRead the original post and maybe you'll find out...

Well, I guess he's referring to the MSDN documents, but I don't see anything wrong or confusing with them, maybe I'm missing something.

##### Share on other sites
Quote:
Original post by kloffy
Quote:
 Original post by FaelenorRead the original post and maybe you'll find out...

Well, I guess he's referring to the MSDN documents, but I don't see anything wrong or confusing with them, maybe I'm missing something.

You're not. The MSDN document is both clear and correct.

##### Share on other sites
If youre improving your C++ skills, then why are you mixing free() (and I assume malloc? in getMem) along with new and delete? Probably want to stick to one or the other, unless I over looked something.

##### Share on other sites
Quote:
 Original post by transistor09Oh, right! The variable gets out of scope, not allocated memory! Way to be confusing, Microsoft!

It's not confusing at all:

Quote:
 Objects allocated with the new operator are not destroyed when the scope in which they are defined is exited.

"Objects allocated" == "allocated memory". This doesn't go out of scope. The variable holding the pointer goes out of scope, because that's what variables normally do.

Quote:
 On the other note, will this recursive destructor be a performance killer?

Well, was it a performance killer to create the nodes in the first place? 'delete' is thought of as faster than 'new', because 'delete' only has to tell the system "this memory is available again", while 'new' has to search for a piece of memory that's big enough. Regardless, it's work that has to be done anyway, so there is no point worrying about how fast it is. The only thing that's at all interesting about it is that you create the nodes one at a time and potentially destroy a bunch of them at once. But it's still not a big issue. Remember, even garbage-collected languages do a full collection over hundreds of megabytes of objects in some few milliseconds. (You can try to make a garbage-collector for C++, but they are not very robust, because the code can't know for sure what is a pointer and what isn't - there are lots of ways to 'hide' a pointer.)

##### Share on other sites
Quote:
 Original post by ChaosEngineYou're not. The MSDN document is both clear and correct.

Sorry if my accusation was a bit harsh, I was just exploiting the stereotype.
Quote:
 Original post by NumberXaeroIf youre improving your C++ skills, then why are you mixing free() (and I assume malloc? in getMem) along with new and delete?

Um, there is an error in original post, I meant to say "malloc:realloc". The new/delete tigger constructor/destructor while malloc/realloc/free allows dynamic arrays without me needing to manually copy the memory. Is it bad anyway (even if I keep track of them and use the appropriate functions)?

##### Share on other sites
Quote:
 Original post by transistor09Um, there is an error in original post, I meant to say "malloc:realloc". The new/delete tigger constructor/destructor while malloc/realloc/free allows dynamic arrays without me needing to manually copy the memory. Is it bad anyway (even if I keep track of them and use the appropriate functions)?

It's error-prone and you don't see it very often, so it might hurt some programmers' eyes. A morally appropriate solution would be using ::std::vector<> to take care of memory management.

##### Share on other sites
Quote:
 Original post by ComicSansMSIt's error-prone...

It's inside a class. Fixed once--fixed forever, right? Although it would be a bad habit.
Quote:
 Original post by ComicSansMS... and you don't see it very often, so it might hurt some programmers' eyes.

Ok, You got me, I'm a crappy programmer...
Quote:
 Original post by ComicSansMSA morally appropriate solution would be using ::std::vector<> to take care of memory management.

What about constructor/destructor? If vector doesn't do that the code would still be mixed.

##### Share on other sites
Quote:
 Original post by transistor09What about constructor/destructor? If vector doesn't do that the code would still be mixed.

not sure what you mean here.

one way to solve this would be to add a ::std::vector<node> class member that will store all nodes maintained by the class. the class can be queried to give pointers/iterators to node objects in that vector. upon destruction, the destructor of ::std::vector is called automatically and will free all nodes it contains. no more worrying about destruction for you [smile]

##### Share on other sites
Quote:
 Original post by ComicSansMSone way to solve this would be to add a ::std::vector class member that will store all nodes maintained by the class. the class can be queried to give pointers/iterators to node objects in that vector. upon destruction, the destructor of ::std::vector is called automatically and will free all nodes it contains. no more worrying about destruction for you [smile]

That sounds nice. I'm going to investigate std::vector some more in next project. Right now my "nodes" work fine for me.

##### Share on other sites
Quote:
 Original post by transistor09What about constructor/destructor? If vector doesn't do that the code would still be mixed.

Malloc allocates memory. New constructs an object. The two operations are not interchangeable.

Of an object needs to be constructed, its constructor needs to be invoked. If it needs a constructor, it probably needs a destructor and a copy and/or move operator set. These things allow a good programmer to provide strong guarantees about behaviour through the use of class invariants.

The std::vector container constructs and destroys the objects it holds. Many objects have trivial constructors or destructors, so it can be like malloc/free if necessary. Pointers are objects with trivial construct/destroy semantics, but because of their usage (eg. possibly pointing to other objects ofdynamic duration) you may be better off storing smart pointers in a vector.

## Create an account

Register a new account

• ## Partner Spotlight

• ### Forum Statistics

• Total Topics
627638
• Total Posts
2978328

• 10
• 12
• 22
• 13
• 34