xian_hong2046 said:
I think dynamic memory allocation is supposed to be used when one
doesn't know in advance how much memory to allocate until run time.
Use it if you don't know if you will need an object or not, and if the
object's lifespan must last longer than the function that creates it.
Otherwise, put the object on the stack. It also dynamically allocates, but
synchronized with method calls so you don't need to explicitely delete
things.
An
example from Thinking in C++ is to dynamically create an array (using
"new") since one doesn't know it size when writing the program.
That is a "Thinking in C" topic, because functions like malloc() are the
only way to create a variable-size array in C.
Read /Accelerated C++/, and use std::vector<> to create an array of variable
size. No 'new' or 'delete'. The vector hides them, making your job much
easier and your code much safer.
However, it looks to me that the size information must come from
somewhere at run time, and this information can be passed to array
creation function as a function's formal argument. Therefore, the
array can still be created using a "static" method. Is this right?
No, because both C and C++ use low-level arrays that are as close to the
metal as possible. Look at this function:
void foo()
{
char slug[99];
...
}
The compiler must know, at compile time, how big to make the foo()
function's stack frame. That's so that (on common implementations) the
compiler can generate the simplest and fastest possible opcodes to create
that stack frame, when foo() starts.
That's why C++ should not permit this:
void foo(int amount)
{
char slug[amount];
....
}
'amount' is not a "hard constant", or "compile time constant". The compiler
cannot guess how big foo's stack frame will be, so it refuses to generate
slower opcodes that calculate this size.
The C languages often make the programmer work a little harder so the
compiler and its output code can work easier and faster.
I'd really appreciate it if someone could advise me when to use dynamic
memory allocation.
This is uncompiled code that might contain syntax errors, but it will get
you started:
typedef std::auto_ptr<SimCity> SimCityPointer;
SimCityPointer cityFactory(string type)
{
if ("skyscrapers" == type)
return SimCityPointer(new SkyScraperCity);
if ("ecotopic" == type)
return SimCityPointer(new EcotopicCity);
if ("shanty" == type)
return SimCityPointer(new ShantyCity);
return SimCityPointer(new NullCity);
}
All the *City classes inherit SimCity.
If the user provides a string for what city they want, we create one and
return it.
The calling functions don't care what kind of city it is, hence they can't
create it themselves. If they could, they might put it on the stack, and not
use 'new'.
Because this function decouples the city creation system from the other
functions, it must safely call 'new', and then ensure that functions who use
the city will indeed call 'delete' on it when they are finished with it.
When you call 'new', you should immediately provide a 'delete'. Don't put
that off or try to remember, later after you write many more client
functions, to write a 'delete'. I provided for a delete by putting the
pointer inside the template std::auto_ptr<>.
Discard any C++ tutorial that doesn't discuss smart pointers!