What is New actualy used for?

Started by
11 comments, last by Zahlman 18 years, 4 months ago
I know how to use new keyword in C++ but why allocate memory for objects? since i thought memory is allocated for objects automaticaly when they are constructed. So is there any reason in using new at all?
Advertisement
Though there are lots of other reasons, one really nice one is dynamic sizing of arrays. Let's say, for whatever reason, you need an array in your program - but you don't know how large it needs to be until part way through running. You aren't allowed to say something like:
int myArray[userSize];

You would have to use:
int *myArray = new int[userSize];
It only takes one mistake to wake up dead the next morning.
You use new to allocate memory for objects whose size you don't know at compile-time.

For example:

Say you need an array of strings to hold names (bad example but it'll work). Well, say this array gets its contents from a file. Maybe one time the file holds 5 names, so your array needs to be size 5... maybe someone edits that file and the next time your array needs to hold 20 names... you have to use new for this (or some containers from the standard library - but im pretty sure they use new/delete behind the scenes).
[edit]too late[/edit]
You also have to remember that newing an object stores it on the heap, whereas regular construction is stored on the stack. The stack is a very finite resource that can't hold extremely large amounts of objects, so sometimes you have no choice.
Quote:Original post by tychon
You also have to remember that newing an object stores it on the heap, whereas regular construction is stored on the stack. The stack is a very finite resource that can't hold extremely large amounts of objects, so sometimes you have no choice.

On that - how does one know when it's becoming important to store on the heap instead of the stack? Will some sort of OS error get shown if the program is out of room on the stack?

Thanks
It only takes one mistake to wake up dead the next morning.
You can get an error because of running out of stack space, but it's unusual to have a real problem with it. The motivation for putting something on the heap is *not knowing* its size. For example, an array that needs to be a different size depending on the contents of some configuration file. This kind of allocation just can't happen on the stack in C++. This is also required generally when polymorphism is desired ([google] 'object slicing').

A constructor call *initializes* the block of memory that was allocated for an object. When you stack-allocate some object, the compiler emits instructions basically to do this:

// C++:{Object foo(1, 2);// Output:// - Code to reserve space on the stack equal to the size of an Object.// - Code invoking the Object constructor code on foo's memory region within// the stack.// C++:}// Output:// - code invoking the Object destructor code on foo's memory region within// the stack.// - code to deallocate that space on the stack.


The stack is indeed a stack in the computer science sense: what is put on (allocated) last, is removed (deallocated) first. This makes it quick to find a spot to place something (we just use a continuous block of memory, and add to or remove from the end). By contrast, the heap is a free-for-all:

// C++:{Object * foo = new Object(1, 2);// Output:// - Code to ask the system for space within the heap the size of an Object.// - Code to cause an exception to be thrown if the system reports that this// can't be done.// - Code invoking the Object constructor code on foo's memory region within// the stack.// C++:}// Output:// Nothing regarding foo!


The object is NOT cleaned up at the end of scope. This allows the object to persist beyond its scope, which is often a useful property.

But beware: "The flip side of 'you get to do your own memory management' is 'you have to do your own memory management'". So do do the deallocation of this, you need to 'delete' the object.

It gets worse: when an allocation is performed by 'new', it *must* be cleaned up by 'delete'. When it is performed by 'new[]', it *must* be cleaned up by 'delete[]'. Anything else is undefined behaviour. And the pointer that you will call delete or delete[] upon has no way to "know" which way it was allocated; you need to track this somehow.
Quote:Original post by Zahlman
You can get an error because of running out of stack space, but it's unusual to have a real problem with it.


Never say never, especially if you approach a recursive function with a hangover. [grin]

Quote:Original post by Frequency
On that - how does one know when it's becoming important to store on the heap instead of the stack? Will some sort of OS error get shown if the program is out of room on the stack?

Thanks


As has been mentioned before, if you don't know how big it is to start with, it goes on the heap. So no matter how big or small it might be in reality, if you don't know, it goes on the heap. Somewhat like that heap of clothes that waits to give birth to the brown and green sock monster.

And as far as errors go, Windows will dump an error message in the event viewer, yes. I can't remember the exact wording behind it, but it more or less says that the application has exceeded its stack resources.
Hi thanks all for that i think i understand now, In creating UIs is it needed to use New? i would recon it is since the sizes can change of the UI.
Quote:Original post by Zahlman
...The motivation for putting something on the heap is *not knowing* its size...

That is one of the primary motivations. Another would be more control over the lifetime of the object. A normal object on the stack exists for the duration of the scope in which it is declared, no longer and no shorter, for all practical purposes of which I am aware. But if it is on the heap, it will remain on the heap as long as you don't remove it from the heap (delete). So if you want to create an object/variable in one function, and then use it later on in some other functions, you can create it on the heap, remember the pointer to where it is, and use it whenever; it will always be there. Well, until you specifically delete it, of course. Or in less common cases, you might want to create a large array, but you want to keep the duration of this array's existence to a minimum, so that you don't use a buttload of system memory for longer than you need it; in some cases, adding extra brackets to define an extra level of scope might not be feasible, or might look ugly, so you can instead new the object right before the moment you need it, and then delete it right after you're done with it.

Of course, in both cases, it might very well be useful to use an appropriate class with appropriate constructors and destructor rather than just calling new and delete raw, to take advantage of RAII. But new and delete will still be hidden in there somewhere, dynamically allocating/deallocating memory.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke

This topic is closed to new replies.

Advertisement