Design question: using malloc?

Discussion in 'C++' started by Christof Krueger, Dec 14, 2003.

  1. Hello,

    I'm quite new to C++ and have some base C knowledge. So I know how to
    solve a given problem, by I sometimes tend to fall back to C. That is
    what I want to avoid in my current project. Therefore I have the
    following question:

    I maintain a list of objects that are created. There is some information
    that is logically related to each instance. I encapulate this in a
    struct like this:

    struct myListEntry {
    myObject entry;
    int relatedData;
    }

    What is the ideal way to implement adding another object to the vector?
    (myVector has type vector<myListEntry> in this example)
    Should I use malloc to reserve memory for my struct?
    Should I do the following?
    ...
    myListEntry newEntry;
    newEntry.entry = something;
    newEntry.relatedData = something_else;
    myVector.push_back(newEntry);
    ...
    Or is there another preferred way?

    Regards,
    Christof Krueger
    Christof Krueger, Dec 14, 2003
    #1
    1. Advertising

  2. "Christof Krueger" <> wrote in message
    news:bripck$jud$03$-online.com...
    > Hello,
    >
    > I'm quite new to C++ and have some base C knowledge. So I know how to
    > solve a given problem, by I sometimes tend to fall back to C. That is
    > what I want to avoid in my current project. Therefore I have the
    > following question:
    >
    > I maintain a list of objects that are created. There is some information
    > that is logically related to each instance. I encapulate this in a
    > struct like this:
    >
    > struct myListEntry {
    > myObject entry;
    > int relatedData;
    > }
    >
    > What is the ideal way to implement adding another object to the vector?
    > (myVector has type vector<myListEntry> in this example)
    > Should I use malloc to reserve memory for my struct?
    > Should I do the following?
    > ...
    > myListEntry newEntry;
    > newEntry.entry = something;
    > newEntry.relatedData = something_else;
    > myVector.push_back(newEntry);
    > ...
    > Or is there another preferred way?
    >
    > Regards,
    > Christof Krueger
    >


    std::vector (and STL containers in general) allocate memory internally as
    required. In this instance, your call to 'push_back' results in a copy of
    the argument being stored in the vector. vector allocates memory for
    the object and uses either a copy constructor or assignment operator to
    initialize it.

    An object stored in a container must at the minimum be 'Assignable'
    which generally means that it has a copy constructor and an assignment
    operator (if it is a simple type or a combination of simple types these are
    not always required).

    If you add these to your struct:

    struct myListEntry {
    myListEntry(const myObject& obj, const int& n)
    : entry(obj), relatedData(n) {}
    myListEntry & operator = (const myListEntry &rhs)
    {
    entry = rhs.entry;
    relatedData = rhs.relatedData;
    return *this;
    }
    myObject entry;
    int relatedData;
    }

    then not only will the code you provided be fine but you could also write:

    myVector.push_back(myListEntry(something, something_else));

    Tom
    Thomas Wintschel, Dec 14, 2003
    #2
    1. Advertising

  3. > If you add these to your struct:
    >
    > struct myListEntry {
    > myListEntry(const myObject& obj, const int& n)
    > : entry(obj), relatedData(n) {}
    > myListEntry & operator = (const myListEntry &rhs)
    > {
    > entry = rhs.entry;
    > relatedData = rhs.relatedData;
    > return *this;
    > }
    > myObject entry;
    > int relatedData;
    > }
    >
    > then not only will the code you provided be fine but you could also write:
    >
    > myVector.push_back(myListEntry(something, something_else));


    I just had to check 3 books (without result) and then search the web to
    find out the difference between struct and class in C++ in detail. Seems
    that the only difference is that in a class the default visibility is
    private and in a struct it is public. Good to know :)

    Thank you very much for your help, Thomas!

    The conclusion is: Dealing with malloc/free in C++ too much (or even at
    all?!?) is not a good idea and should be avoided by using save
    components from STL. Is that right?

    Bye,
    Christof
    Christof Krueger, Dec 14, 2003
    #3
  4. Christof Krueger

    someone else Guest

    "Christof Krueger" <> wrote in message
    news:brisor$l49$04$-online.com...
    > > If you add these to your struct:
    > >
    > > struct myListEntry {
    > > myListEntry(const myObject& obj, const int& n)
    > > : entry(obj), relatedData(n) {}
    > > myListEntry & operator = (const myListEntry &rhs)
    > > {
    > > entry = rhs.entry;
    > > relatedData = rhs.relatedData;
    > > return *this;
    > > }
    > > myObject entry;
    > > int relatedData;
    > > }
    > >
    > > then not only will the code you provided be fine but you could also

    write:
    > >
    > > myVector.push_back(myListEntry(something, something_else));

    >
    > I just had to check 3 books (without result) and then search the web to
    > find out the difference between struct and class in C++ in detail. Seems
    > that the only difference is that in a class the default visibility is
    > private and in a struct it is public. Good to know :)
    >
    > Thank you very much for your help, Thomas!
    >
    > The conclusion is: Dealing with malloc/free in C++ too much (or even at
    > all?!?) is not a good idea and should be avoided by using save
    > components from STL. Is that right?
    >
    > Bye,
    > Christof
    >

    I just wanted to add that TTBOMK the 'new' and 'delete' operators are
    the c++ way to allocate and free memory

    someone else
    someone else, Dec 15, 2003
    #4
  5. Christof Krueger

    David Harmon Guest

    On Mon, 15 Dec 2003 00:48:29 +0100 in comp.lang.c++, Christof Krueger
    <> was alleged to have written:
    >I just had to check 3 books (without result) and then search the web to
    >find out the difference between struct and class in C++ in detail. Seems
    >that the only difference is that in a class the default visibility is
    >private and in a struct it is public. Good to know :)


    This issue is covered in question "[7.8] What's the difference between the
    keywords struct and class?" of Marshall Cline's C++ FAQ. You can get the
    FAQ at: http://www.parashift.com/cpp-faq-lite/

    >The conclusion is: Dealing with malloc/free in C++ too much (or even at
    >all?!?) is not a good idea and should be avoided by using save
    >components from STL. Is that right?


    Short answer: yes.
    David Harmon, Dec 15, 2003
    #5
  6. David Harmon wrote:

    > On Mon, 15 Dec 2003 00:48:29 +0100 in comp.lang.c++, Christof Krueger
    > <> was alleged to have written:
    >
    >>I just had to check 3 books (without result) and then search the web to
    >>find out the difference between struct and class in C++ in detail. Seems
    >>that the only difference is that in a class the default visibility is
    >>private and in a struct it is public. Good to know :)

    >
    >
    > This issue is covered in question "[7.8] What's the difference between the
    > keywords struct and class?" of Marshall Cline's C++ FAQ. You can get the
    > FAQ at: http://www.parashift.com/cpp-faq-lite/

    That was exactly where I found the answer on the web.
    I bookmarked this FAQ as it looks very interesting.

    >
    >>The conclusion is: Dealing with malloc/free in C++ too much (or even at
    >>all?!?) is not a good idea and should be avoided by using save
    >>components from STL. Is that right?

    >
    >
    > Short answer: yes.

    Thanks.
    Christof Krueger, Dec 15, 2003
    #6
  7. Christof Krueger

    Paul Guest

    "Christof Krueger" <> wrote in message
    news:bripck$jud$03$-online.com...
    > Hello,
    >
    > Should I use malloc to reserve memory for my struct?


    Never use malloc unless you know darn well that the struct consists of all
    POD (Plain-Old-Data) members, *and will always consist of POD types*.. If
    you need to dynamically create an object, use operator new. The reason is
    that if you happen to change your struct to have, say a std::string, as a
    member, your malloc() call will introduce undefined behavior. To guard
    against this, you use the C++ way of creating an object, and that is by
    invoking the proper constructor. Operator new calls this constructor when
    you create the object dynamiclly, while malloc doesn't know squat about C++
    objects or constructors. Your struct contains a "myObject" member. Is this
    a POD type? If it isn't, your call to malloc cannot be used safely, period.

    The same thing can be stated for many functions from the 'C'-library. For
    example, using memcpy() and memset() on non-POD types leads to undefined
    behavior, calling qsort() on non-POD types again, undefined behavior. I
    once had to correct a problem where a programmer had a struct of all int
    members and used memset() to initialize all members to 0. Then one day, a
    std::string object was introduced. The call to memset() was never changed,
    and the application that was working was all of a sudden crashing. Chaning
    the memset() to proper initialization via constructor corrected the problem.

    Basically, you should completely get out of defaulting to using 'C'
    functions such as malloc(), since not only are they not necessary for your
    case, it is invalid to use them in many circumstances.

    Paul
    Paul, Dec 15, 2003
    #7
  8. Paul wrote:

    > "Christof Krueger" <> wrote in message
    > news:bripck$jud$03$-online.com...
    >
    >>Hello,
    >>
    >>Should I use malloc to reserve memory for my struct?

    >
    >
    > Never use malloc unless you know darn well that the struct consists of all
    > POD (Plain-Old-Data) members, *and will always consist of POD types*.. If
    > you need to dynamically create an object, use operator new. The reason is
    > that if you happen to change your struct to have, say a std::string, as a
    > member, your malloc() call will introduce undefined behavior. To guard
    > against this, you use the C++ way of creating an object, and that is by
    > invoking the proper constructor. Operator new calls this constructor when
    > you create the object dynamiclly, while malloc doesn't know squat about C++
    > objects or constructors. Your struct contains a "myObject" member. Is this
    > a POD type? If it isn't, your call to malloc cannot be used safely, period.
    >
    > The same thing can be stated for many functions from the 'C'-library. For
    > example, using memcpy() and memset() on non-POD types leads to undefined
    > behavior, calling qsort() on non-POD types again, undefined behavior. I
    > once had to correct a problem where a programmer had a struct of all int
    > members and used memset() to initialize all members to 0. Then one day, a
    > std::string object was introduced. The call to memset() was never changed,
    > and the application that was working was all of a sudden crashing. Chaning
    > the memset() to proper initialization via constructor corrected the problem.
    >
    > Basically, you should completely get out of defaulting to using 'C'
    > functions such as malloc(), since not only are they not necessary for your
    > case, it is invalid to use them in many circumstances.
    >
    > Paul


    Thanks for your explanation of the problem, Paul.
    So when I have non-POD types in my structure (let's take your example
    with a struct full of ints and now with a std::string), is the situation
    the following or am I taking something wrong(?): The std::string data is
    allocated next to all the ints in memory and using a C function like
    memset would set everything in the struct to 0, not only the character
    date in std::string, but also other members???

    My problem (until now) was, that I wasn't sure if it is good to use c++
    features only, because it seemed some kind of inefficient and indirect
    to me. But if programming pure c++ is commonly used in wild life, it
    can't be that bad, so I'll try to get used to avoid mixing C and C++.

    Thanks for your replies!

    Christof Krueger
    Christof Krueger, Dec 15, 2003
    #8
  9. Christof Krueger

    Paul Guest

    "Christof Krueger" <> wrote in message
    news:brj79g$4ti$06$-online.com...

    > So when I have non-POD types in my structure (let's take your example
    > with a struct full of ints and now with a std::string), is the situation
    > the following or am I taking something wrong(?): The std::string data is
    > allocated next to all the ints in memory and using a C function like
    > memset would set everything in the struct to 0, not only the character
    > date in std::string, but also other members???


    You've gotta get out of the 'C' mind Christof ;) In C, all your types are
    POD, so the "rules" you are used to for POD should apply to non-POD right?
    No. When your struct contains non-POD membera, the only way to initialize
    the struct, and thereby the members, is by constructing it correctly. You
    do not construct or initialize such objects using malloc and memset. That's
    the bottom line.

    What if the std::string needs to have specific members set correctly on
    construction? How does malloc()-ing the memory for the struct set up these
    members? It can't -- like I said, malloc() knows zip, zero, nada, about C++
    objects. When you now use the improperly constructed object, what do you
    think will happen if you use such an object? The only thing that sets up
    the members correctly is the constructor call, and only operator new can do
    this (if you create the object dynamically).

    Now, what if the std::string is a reference-counted string? If you used
    memcpy() on such an item, you will screw up the reference counting
    mechanism. This is exactly the situation I mentioned in my previous post
    where the program crashed.

    >
    > My problem (until now) was, that I wasn't sure if it is good to use c++
    > features only, because it seemed some kind of inefficient and indirect
    > to me. But if programming pure c++ is commonly used in wild life, it
    > can't be that bad, so I'll try to get used to avoid mixing C and C++.
    >


    Another thing that 'C' programmers tend to think is that their C code is
    faster than C++. Not only is this, for the most part, a bogus claim, it
    also leads to coding improperly and incorrectly when you resort to coding in
    the 'C'-style.

    Paul
    Paul, Dec 15, 2003
    #9
  10. Paul wrote:

    > "Christof Krueger" <> wrote in message
    > news:brj79g$4ti$06$-online.com...
    >
    >
    >>So when I have non-POD types in my structure (let's take your example
    >>with a struct full of ints and now with a std::string), is the situation
    >>the following or am I taking something wrong(?): The std::string data is
    >>allocated next to all the ints in memory and using a C function like
    >>memset would set everything in the struct to 0, not only the character
    >>date in std::string, but also other members???

    >
    >
    > You've gotta get out of the 'C' mind Christof ;) In C, all your types are
    > POD, so the "rules" you are used to for POD should apply to non-POD right?
    > No. When your struct contains non-POD membera, the only way to initialize
    > the struct, and thereby the members, is by constructing it correctly. You
    > do not construct or initialize such objects using malloc and memset. That's
    > the bottom line.

    Okay, just wanted to know "what if", to understand what happens behind
    the scenes.

    > What if the std::string needs to have specific members set correctly on
    > construction? How does malloc()-ing the memory for the struct set up these
    > members? It can't -- like I said, malloc() knows zip, zero, nada, about C++
    > objects. When you now use the improperly constructed object, what do you
    > think will happen if you use such an object? The only thing that sets up
    > the members correctly is the constructor call, and only operator new can do
    > this (if you create the object dynamically).
    >
    > Now, what if the std::string is a reference-counted string? If you used
    > memcpy() on such an item, you will screw up the reference counting
    > mechanism. This is exactly the situation I mentioned in my previous post
    > where the program crashed.
    >
    >
    >>My problem (until now) was, that I wasn't sure if it is good to use c++
    >>features only, because it seemed some kind of inefficient and indirect
    >>to me. But if programming pure c++ is commonly used in wild life, it
    >>can't be that bad, so I'll try to get used to avoid mixing C and C++.
    >>

    >
    >
    > Another thing that 'C' programmers tend to think is that their C code is
    > faster than C++. Not only is this, for the most part, a bogus claim, it
    > also leads to coding improperly and incorrectly when you resort to coding in
    > the 'C'-style.

    I'me quite new to C and C++ programming both but I've seen more C code
    than C++ code _before_ I started to actually program it myself. That is
    why I still mix things up.
    C code look intuitively faster, because its more complicated (not that
    high level) and one think, that c++ programs have more overhead to
    handle. But of course you can write a lot of *really* slow code in
    low-level C :)
    If you know some must-see links covering performance comparison between
    C/C++ programs, please let me know.

    Christof
    Christof Krueger, Dec 15, 2003
    #10
  11. > > Another thing that 'C' programmers tend to think is that their C code
    is
    > > faster than C++. Not only is this, for the most part, a bogus claim,

    it
    > > also leads to coding improperly and incorrectly when you resort to

    coding in
    > > the 'C'-style.

    > I'me quite new to C and C++ programming both but I've seen more C code
    > than C++ code _before_ I started to actually program it myself. That is
    > why I still mix things up.
    > C code look intuitively faster, because its more complicated (not that
    > high level) and one think, that c++ programs have more overhead to
    > handle. But of course you can write a lot of *really* slow code in
    > low-level C :)
    > If you know some must-see links covering performance comparison between
    > C/C++ programs, please let me know.


    You might find this one an interesting read:
    http://www.objectmentor.com/resources/articles/WhyAreYouStillUsingC.pdf

    My advise is don't be overly concerned with performance. Though it is a bit
    easier to write inefficient code in C++ than in C, well written C++ code
    can be just as fast as well written C code. Often there are more important
    concerns than performance, like correctness, maintainability and speed of
    development. C++ offers a better compromise between efficiency and elegancy
    than C code. My exprience is that only a small part of the code is really
    relevant for the performance of an application. On modern hardware most
    applications will run fast enough without using dirty tricks. Also many
    applications are are more limited by I/O performance than CPU performance,
    coding tricks to save CPU cycles won't help in this case.

    --
    Peter van Merkerk
    peter.van.merkerk(at)dse.nl
    Peter van Merkerk, Dec 15, 2003
    #11
    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. John
    Replies:
    13
    Views:
    685
  2. ravi
    Replies:
    0
    Views:
    439
  3. Peter
    Replies:
    34
    Views:
    1,916
    Richard Tobin
    Oct 22, 2004
  4. porting non-malloc code to malloc

    , Feb 18, 2005, in forum: C Programming
    Replies:
    3
    Views:
    468
    Walter Roberson
    Feb 19, 2005
  5. Johs32

    to malloc or not to malloc??

    Johs32, Mar 30, 2006, in forum: C Programming
    Replies:
    4
    Views:
    313
    Captain Winston
    Mar 30, 2006
Loading...

Share This Page