when to use dynamic memory allocation?

Discussion in 'C++' started by xian_hong2046@hotmail.com, Apr 8, 2006.

  1. Guest

    Hello,

    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. 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.
    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?

    I'd really appreciate it if someone could advise me when to use dynamic
    memory allocation.

    Many thanks!
    xian
     
    , Apr 8, 2006
    #1
    1. Advertising

  2. Phlip Guest

    xian_hong2046 wrote:

    > 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!

    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Apr 8, 2006
    #2
    1. Advertising

  3. Guest

    Hi Phlip,

    Many thanks for your detailed explanation, that really helped!

    xian
     
    , Apr 8, 2006
    #3
  4. Daniel T. Guest

    In article <>,
    "" <> wrote:

    > Hello,
    >
    > 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. 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.


    Those kinds of issues are addressed in the standard library. If you
    don't know how many objects you need until runtime, use a container.

    > I'd really appreciate it if someone could advise me when to use dynamic
    > memory allocation.


    You should use dynamic memory allocation directly when you don't know
    the *type* of the object you are creating until runtime.


    --
    Magic depends on tradition and belief. It does not welcome observation,
    nor does it profit by experiment. On the other hand, science is based
    on experience; it is open to correction by observation and experiment.
     
    Daniel T., Apr 8, 2006
    #4
  5. Daniel T. Guest

    In article <mzHZf.9128$%>,
    "Phlip" <> wrote:

    > xian_hong2046 wrote:
    >
    > > 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.


    I think that the above isn't general enough. For example, a constructor
    can create an object, and the destructor destroy it, without it being
    newed or deleted.

    I was think of some rule like "if the scopes don't match" but you can
    always create a scope that matches the objects lifetime so that doesn't
    work either...

    > > 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.


    The above is a good explanation but it doesn't match the general rule
    given, your using 'new' because you don't know what type of city you
    will need until runtime, not because it outlives the function.


    --
    Magic depends on tradition and belief. It does not welcome observation,
    nor does it profit by experiment. On the other hand, science is based
    on experience; it is open to correction by observation and experiment.
     
    Daniel T., Apr 9, 2006
    #5
  6. Phlip Guest

    Daniel T. wrote:

    >> 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.

    >
    > I think that the above isn't general enough. For example, a constructor
    > can create an object, and the destructor destroy it, without it being
    > newed or deleted.
    >
    > I was think of some rule like "if the scopes don't match" but you can
    > always create a scope that matches the objects lifetime so that doesn't
    > work either...


    The goal here is to find just the right verbiage that leads no newbie
    astray, but doesn't depend on the advanced terms like "scope" or "RAII" or
    "deterministic destruction".

    So, "don't call 'new' until you exhaust the simpler alternatives", and
    "vector is simpler than new[] for arrays".

    > The above is a good explanation but it doesn't match the general rule
    > given, your using 'new' because you don't know what type of city you
    > will need until runtime, not because it outlives the function.


    Right. I'm so advanced that I can't think of the simplest possible scenario
    that demands 'new'.

    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Apr 9, 2006
    #6
  7. Daniel T. Guest

    In article <4sZZf.23724$>,
    "Phlip" <> wrote:

    > Daniel T. wrote:
    >
    > > The above is a good explanation but it doesn't match the general rule
    > > given, your using 'new' because you don't know what type of city you
    > > will need until runtime, not because it outlives the function.

    >
    > Right. I'm so advanced that I can't think of the simplest possible scenario
    > that demands 'new'.


    :) I disagree, you aren't that advanced. That *is* the simplest
    possible scenario that demands 'new'. The only time that 'new' is
    demanded is when you don't know what sub-type to make until runtime.


    --
    Magic depends on tradition and belief. It does not welcome observation,
    nor does it profit by experiment. On the other hand, science is based
    on experience; it is open to correction by observation and experiment.
     
    Daniel T., Apr 9, 2006
    #7
  8. Guest

    Hi Daniel and Phlip,

    Thanks to both of you for the discussions, I find them very useful
    indeed.

    May I please ask you another two questions, which may be quite trivial
    to you?

    I had a simple file like:

    #include <iostream>
    using namespace std;

    int i;

    i = 10;
    int main(){
    cout << i << endl;
    }

    But it couldn't compile. However, if I combined the declarations and
    definitions of "i" into one:

    int i = 10

    then it all worked out. It also worked if I moved "i=10" into the body
    of "main". What's the problem?

    Another question concerns the use of "extern". It should be used when
    one declares a function or variable that has been defined in another
    file or will be defined later in this file. If the variable/function
    is declared in a .h file (but no definitions are provided in the .h
    file), then after I include the header file, do I still need to use
    "extern" before I use that function/variable? From my experiments, it
    looks like I don't have to. But according to the purpose of "extern",
    it seems that I should use "extern".

    Many thanks,
    xian
     
    , Apr 9, 2006
    #8
  9. Phlip Guest

    Daniel T. wrote:

    > The only time that 'new' is
    > demanded is when you don't know what sub-type to make until runtime.


    A. What example would you give an absolute new newbie?

    B. I'm certain I have used new for simpler situations. I'm aware
    some of them could have been NullObjects, or the equivalent.
    Are you convinced that's the _only_ time new is demanded??

    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Apr 9, 2006
    #9
  10. Phlip Guest

    wrote:

    > int i;
    >
    > i = 10;
    > int main(){
    > cout << i << endl;
    > }


    Only declarations, definitions, and initializations may appear outside of
    functions or constructors. (And namespaces, typedefs, preprocessor
    statements, and other bric-a-brac that some language lawyer wannabe is sure
    to jump all over me about.)

    This is permitted outside of functions:

    > int i = 10


    i = 10; is not because it's not part of the action of defining x.
    Initialization is.

    > Another question concerns the use of "extern". It should be used when
    > one declares a function or variable that has been defined in another
    > file or will be defined later in this file. If the variable/function
    > is declared in a .h file (but no definitions are provided in the .h
    > file), then after I include the header file, do I still need to use
    > "extern" before I use that function/variable? From my experiments, it
    > looks like I don't have to. But according to the purpose of "extern",
    > it seems that I should use "extern".


    It's optional on function declarations and not

    The deal here is a "translation unit" that's usually one .cpp file that
    creates one .o or .obj file. After you put all the .h files together
    into .cpp file, the result is a "translation unit" that then gets compiled
    into opcodes.

    For a given global int Foo, all translation units that need the Foo should
    see an 'extern int Foo;'. But only one translation unit needs 'int Foo =
    42;'. That's so the opcodes that create the Foo itself will only compile in
    one spot, and only go into one .o or .obj file.

    Now don't use extern, and learn not to make global variables. Make global
    functions instead, so the code stays more flexible.

    >
    > Many thanks,
    > xian


    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Apr 9, 2006
    #10
  11. Daniel T. Guest

    In article <v7_Zf.23727$>,
    Phlip <> wrote:

    > Daniel T. wrote:
    >
    > > The only time that 'new' is
    > > demanded is when you don't know what sub-type to make until runtime.

    >
    > A. What example would you give an absolute new newbie?


    I think your example was perfect.

    > B. I'm certain I have used new for simpler situations. I'm aware
    > some of them could have been NullObjects, or the equivalent.
    > Are you convinced that's the _only_ time new is demanded??


    "Convinced" is such a strong word. Let's just say I've thought of a few
    situations where new could be used and proven to myself that in each of
    those cases the object could have been put on the stack, except of
    course if you don't know what type to create until runtime. For example:

    The OP said something like "use new when you don't know how many objects
    to create." As you and I both said, though this is true, the standard
    container classes do all the work for you so just use them.

    Another possible reason (you alluded to,) "use new when the object will
    outlive the scope it's created in." In any case like that, you can
    create a scope that encompasses the objects lifetime.

    Another (mine) is "use new when you don't know what type the object will
    be until runtime."

    I'm thinking the real answer is "all three". If you don't know how many
    objects you need, or how long they should live, or what types they are
    until runtime, you have to create them dynamically.

    So, it's easy to come up with an example where we don't know what kind
    of object to make until runtime, it's also easy to come up with an
    example where we don't know how many to make. Can we come up with an
    example where we don't know the objects lifetime until runtime? [some
    thought] I got it, a state pattern where the states are determined by
    the user's actions. That's not really an example though, it's the
    metaphor for an example. Care to make the actual example?


    --
    Magic depends on tradition and belief. It does not welcome observation,
    nor does it profit by experiment. On the other hand, science is based
    on experience; it is open to correction by observation and experiment.
     
    Daniel T., Apr 9, 2006
    #11
  12. Guest

    Many thanks for your explanation! I just have another problem
    regarding 'extern': although I can avoid using global variables, it may
    be necessary at some point...

    I have an example .h file (foo.h), which looks like this:

    struct myStruct{
    int n;
    void print();
    void init(int val);
    };

    int i;

    Then in foo.cpp I have:

    #include <iostream>
    #include "foo.h"
    using namespace std;

    void myStruct::init(int n){
    this->n = n;
    }

    void myStruct::print(){
    cout << n << endl;
    }

    int i = 9;

    Finally, I tested foo.cpp by foo_test.cpp:

    #include <iostream>
    #include "foo.h"
    using namespace std;

    int main(){
    myStruct s;
    s.init(8);
    s.print();
    cout << i << endl;
    }

    and it doesn't work. It turned out that I need to have "extern int i;"
    in foo.h to make it work. Why is it not necessary to put "extern" for
    myStruct.init or myStruct.print before I use them, while it is
    essential to have "extern" for the global int?

    Thanks!
    xian
     
    , Apr 9, 2006
    #12
  13. Daniel T. Guest

    In article <>,
    "" <> wrote:

    > Hi Daniel and Phlip,
    >
    > Thanks to both of you for the discussions, I find them very useful
    > indeed.
    >
    > May I please ask you another two questions, which may be quite trivial
    > to you?
    >
    > I had a simple file like:
    >
    > #include <iostream>
    > using namespace std;
    >
    > int i;
    >
    > i = 10;
    > int main(){
    > cout << i << endl;
    > }
    >
    > But it couldn't compile. However, if I combined the declarations and
    > definitions of "i" into one:
    >
    > int i = 10
    >
    > then it all worked out. It also worked if I moved "i=10" into the body
    > of "main". What's the problem?


    The only constructs that may exist outside of any parentheses are
    declarations and definitions. "i = 10;" is neither, it is a statement so
    it cannot live outside of a set of parentheses. "int i = 10;" is a
    definition, so it can.


    > Another question concerns the use of "extern". It should be used when
    > one declares a function or variable that has been defined in another
    > file or will be defined later in this file. If the variable/function
    > is declared in a .h file (but no definitions are provided in the .h
    > file), then after I include the header file, do I still need to use
    > "extern" before I use that function/variable? From my experiments, it
    > looks like I don't have to. But according to the purpose of "extern",
    > it seems that I should use "extern".


    You know, I started to write a whole article on external vs internal
    linkage but I think it's too complicated to bother with. Just try to
    remember the rule below until you get beyond the stage where you are
    asking about basic constructs.

    When you want to use a global variable in a cpp file that it isn't
    defined in, you have to declare it with "extern".



    --
    Magic depends on tradition and belief. It does not welcome observation,
    nor does it profit by experiment. On the other hand, science is based
    on experience; it is open to correction by observation and experiment.
     
    Daniel T., Apr 9, 2006
    #13
  14. Guest

    Thanks, Daniel!

    xian
     
    , Apr 10, 2006
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roman Hartmann

    structs and dynamic memory allocation

    Roman Hartmann, Nov 4, 2003, in forum: C Programming
    Replies:
    11
    Views:
    515
    Roman Hartmann
    Nov 5, 2003
  2. s.subbarayan

    Dynamic memory allocation and memory leak...

    s.subbarayan, Mar 18, 2005, in forum: C Programming
    Replies:
    10
    Views:
    709
    Eric Sosman
    Mar 22, 2005
  3. Ken
    Replies:
    24
    Views:
    3,879
    Ben Bacarisse
    Nov 30, 2006
  4. chris
    Replies:
    6
    Views:
    998
    chris
    Oct 28, 2005
  5. Bjarke Hammersholt Roune
    Replies:
    14
    Views:
    1,199
    Bjarke Hammersholt Roune
    Mar 6, 2011
Loading...

Share This Page