Unless you are forced to use C, you should never use malloc. Always use new.
If you need a big chunk of data just do something like:
char *pBuffer = new char[1024];
Be careful though this is not correct:
//This is incorrect - may delete only one element, may corrupt the heap, or worse...
delete pBuffer;
Instead you should do this when deleting an array of data:
//This deletes all items in the array
delete[] pBuffer;
The new keyword is the C++ way of doing it, and it will ensure that your type will have its constructor called. The new keyword is also more type-safe whereas malloc is not type-safe at all.
The only way I could think that would be beneficial to use malloc would be if you needed to change the size of your buffer of data. The new keyword does not have an analogous way like realloc. The realloc function might be able to extend the size of a chunk of memory for you more efficiently.
It is worth mentioning that you cannot mix new/free and malloc/delete.
Note: Some answers in this question are invalid.
int* p_scalar = new int(5); // Does not create 5 elements, but initializes to 5
int* p_array = new int[5]; // Creates 5 elements
Answer from Brian R. Bondy on Stack OverflowUnless you are forced to use C, you should never use malloc. Always use new.
If you need a big chunk of data just do something like:
char *pBuffer = new char[1024];
Be careful though this is not correct:
//This is incorrect - may delete only one element, may corrupt the heap, or worse...
delete pBuffer;
Instead you should do this when deleting an array of data:
//This deletes all items in the array
delete[] pBuffer;
The new keyword is the C++ way of doing it, and it will ensure that your type will have its constructor called. The new keyword is also more type-safe whereas malloc is not type-safe at all.
The only way I could think that would be beneficial to use malloc would be if you needed to change the size of your buffer of data. The new keyword does not have an analogous way like realloc. The realloc function might be able to extend the size of a chunk of memory for you more efficiently.
It is worth mentioning that you cannot mix new/free and malloc/delete.
Note: Some answers in this question are invalid.
int* p_scalar = new int(5); // Does not create 5 elements, but initializes to 5
int* p_array = new int[5]; // Creates 5 elements
The short answer is: don't use malloc for C++ without a really good reason for doing so. malloc has a number of deficiencies when used with C++, which new was defined to overcome.
Deficiencies fixed by new for C++ code
mallocis not typesafe in any meaningful way. In C++ you are required to cast the return fromvoid*. This potentially introduces a lot of problems:#include <stdlib.h> struct foo { double d[5]; }; int main() { foo *f1 = malloc(1); // error, no cast foo *f2 = static_cast<foo*>(malloc(sizeof(foo))); foo *f3 = static_cast<foo*>(malloc(1)); // No error, bad }It's worse than that though. If the type in question is POD (plain old data) then you can semi-sensibly use
mallocto allocate memory for it, asf2does in the first example.It's not so obvious though if a type is POD. The fact that it's possible for a given type to change from POD to non-POD with no resulting compiler error and potentially very hard to debug problems is a significant factor. For example if someone (possibly another programmer, during maintenance, much later on were to make a change that caused
footo no longer be POD then no obvious error would appear at compile time as you'd hope, e.g.:struct foo { double d[5]; virtual ~foo() { } };would make the
mallocoff2also become bad, without any obvious diagnostics. The example here is trivial, but it's possible to accidentally introduce non-PODness much further away (e.g. in a base class, by adding a non-POD member). If you have C++11/boost you can useis_podto check that this assumption is correct and produce an error if it's not:#include <type_traits> #include <stdlib.h> foo *safe_foo_malloc() { static_assert(std::is_pod<foo>::value, "foo must be POD"); return static_cast<foo*>(malloc(sizeof(foo))); }Although boost is unable to determine if a type is POD without C++11 or some other compiler extensions.
mallocreturnsNULLif allocation fails.newwill throwstd::bad_alloc. The behaviour of later using aNULLpointer is undefined. An exception has clean semantics when it is thrown and it is thrown from the source of the error. Wrappingmallocwith an appropriate test at every call seems tedious and error prone. (You only have to forget once to undo all that good work). An exception can be allowed to propagate to a level where a caller is able to sensibly process it, where asNULLis much harder to pass back meaningfully. We could extend oursafe_foo_mallocfunction to throw an exception or exit the program or call some handler:#include <type_traits> #include <stdlib.h> void my_malloc_failed_handler(); foo *safe_foo_malloc() { static_assert(std::is_pod<foo>::value, "foo must be POD"); foo *mem = static_cast<foo*>(malloc(sizeof(foo))); if (!mem) { my_malloc_failed_handler(); // or throw ... } return mem; }Fundamentally
mallocis a C feature andnewis a C++ feature. As a resultmallocdoes not play nicely with constructors, it only looks at allocating a chunk of bytes. We could extend oursafe_foo_mallocfurther to use placementnew:#include <stdlib.h> #include <new> void my_malloc_failed_handler(); foo *safe_foo_malloc() { void *mem = malloc(sizeof(foo)); if (!mem) { my_malloc_failed_handler(); // or throw ... } return new (mem)foo(); }Our
safe_foo_mallocfunction isn't very generic - ideally we'd want something that can handle any type, not justfoo. We can achieve this with templates and variadic templates for non-default constructors:#include <functional> #include <new> #include <stdlib.h> void my_malloc_failed_handler(); template <typename T> struct alloc { template <typename ...Args> static T *safe_malloc(Args&&... args) { void *mem = malloc(sizeof(T)); if (!mem) { my_malloc_failed_handler(); // or throw ... } return new (mem)T(std::forward(args)...); } };Now though in fixing all the issues we identified so far we've practically reinvented the default
newoperator. If you're going to usemallocand placementnewthen you might as well just usenewto begin with!
Hi there, I'm currently reimplementing the small block memory allocator used by Box2D to get a better understanding of what it's doing, and I was wondering why, despite being a C++ library and not C, it uses malloc and free as its default allocator when allocating larger blocks of memory.
Is there a good reason for this or just an example of using C in C++? I assume new and delete are not used because they don't want to initialise anything in the newly allocated area, but wouldn't ::operator new and ::operator delete do this however?
Have I understood correctly that ::operator new and ::operator delete do largely the same thing as malloc and free?
new and delete are C++ specific features. They didn't exist in C. malloc is the old school C way to do things. Most of the time, you won't need to use it in C++.
mallocallocates uninitialized memory. The allocated memory has to be released withfree.callocis likemallocbut initializes the allocated memory with a constant (0). It needs to be freed withfree.newinitializes the allocated memory by calling the constructor (if it's an object). Memory allocated withnewshould be released withdelete(which in turn calls the destructor). It does not need you to manually specify the size you need and cast it to the appropriate type. Thus, it's more modern and less prone to errors.
new/delete + new[]/delete[]:
new/deleteis the C++ way to allocate memory and deallocate memory from the heap.new[]anddelete[]is the C++ way to allocate arrays of contiguous memory.- Should be used because it is more type safe than
malloc - Should be used because it calls the constructor/destructor
- Cannot be used in a
reallocway, but can use placement new to re-use the same buffer of data - Data cannot be allocated with
newand freed withfree, nordelete[]
malloc/free + family:
malloc/free/family is the C way to allocate and free memory from the heap.callocis the same asmallocbut also initializes the memory- Should be used if you may need to reallocate the memory
- Data cannot be allocated with
mallocand freed with delete nor delete[]
Also see my related answer here