4

In Exceptional C++, Herb Sutter wrote in Item 35 as a guideline:

Prefer using the free store (new/delete). Avoid using the heap (malloc/free).

Why should I?

If an implementation chooses to implement new by using malloc, an overhead would probably incur, so that looks like a bad piece of advice as far as performance is concerned.

qdii
  • 12,505
  • 10
  • 59
  • 116
  • 1
    http://stackoverflow.com/questions/1350819/c-free-store-vs-heap - seems to answer your question – DarkWanderer May 06 '13 at 18:23
  • 6
    `malloc/free` don't have the faintest idea what constructors and destructors are. This is enough of a reason to always use `new/delete`. – syam May 06 '13 at 18:23
  • @syam: Thank you, but I think that any reader of Exceptional C++ already had an idea on the difference between `malloc` and `new`. I hope that the book author was trying to make another point. – qdii May 06 '13 at 18:26
  • @DarkWanderer it does not: your link explains the difference between `new` and `malloc`, my question is “why is it best to use the former?” – qdii May 06 '13 at 18:27
  • @qdii: please read it again. The OP specifically asced on differences between free store and heap and NOT about malloc/free. The accepted answer gives a nice explanation. – DarkWanderer May 06 '13 at 18:29
  • Also, there's a link on another Herb Sutter text, from where the citations came from: http://www.gotw.ca/gotw/009.htm – DarkWanderer May 06 '13 at 18:31
  • @qdii: I get your point. But I still think that, once you get rid of all the standardese lingo, that's what it boils down to. – syam May 06 '13 at 18:33

1 Answers1

11

The new and delete keywords in C++ usually are implemented in terms of malloc and free, but they're designed to do different things.

In C++, if you say

new T(/* args */)

C++ will do the following:

  • Attempt to allocate enough memory to hold an object of type T.
  • On failure, attempt to use the new handler to free space, eventually throwing a std::bad_alloc object if no memory is available.
  • Attempt construct an object of type T in that block of memory.
  • Automatically deallocate the memory if the construction of the object of type T throws an exception.

If you just use malloc, you have to do all of these steps manually, which would be very, very hard. It might look something like this:

T* memory = nullptr;
while (true) {
   memory = static_cast<T*>(malloc(sizeof(T)));
   if (memory != nullptr) break;

   std::get_new_handler()();  
}

try {
    new (memory) T(/* args */);
} catch (...) {
    free(memory);
    throw;
}

There are some other nuances here that I've glossed over (like calling operator new instead of malloc, or handling zero-sized requests, etc.), but I hope this helps explain how new and malloc are different.

So why should you use new over malloc? Well, there's a few reasons:

  • It's much safer. With malloc you can forget to check the return type for a null pointer, or you could request the wrong amount of storage space, or you could forget to call the constructor on the object, or you could forget to deallocate memory if the constructor throws an exception, etc.

  • It's more type-safe. malloc returns a void*, which is just a pointer to a block of memory. Using malloc, you have to cast the pointer to the proper type, which introduces the potential for errors later on.

  • It allows customization. Certain types overload operator new to request memory in an unusual way, such as from a pooled allocator or from certain pieces of memory that might be faster, or using a custom allocator that optimizes over the usage pattern. Given this, you can automatically customize all times where memory is allocated dynamically for an object of type T simply by defining operator new and operator delete. If you use malloc, you have to chase down all memory allocation sites throughout the entire program.

That said, there are some advantages to malloc. If you know for certain that you're allocating objects that are trivial objects (like primitives or structs that just hold data), it might be slightly faster to use malloc. malloc also lets you use realloc, which free doesn't. But honestly, you're probably better off just using std::vector or std::array in cases like this, since they're safer, easier to debug, and with good compiler support are likely to be aggressively optimized.

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065