Difference between global non-throwing ::operator new and std::malloc
The main differences, aside from syntax and free
vs. delete
, are
- you can portably replace
::operator new
; malloc
comes withrealloc
, for whichnew
has no equivalent;new
has the concept of anew_handler
, for which there is nomalloc
equivalent.
(Replacing malloc
opens up a can of worms. It can be done, but not portably, because it requires knowledge of the linker.)
Regarding the differences between malloc and new in terms of their respective mechanisms of handling memory allocation?
malloc
doesn't throwbad_alloc
exception asnew
does.- Because malloc doesn't throw exceptions, you have to check its result against
NULL
(or nullptr in c++11 and above), which isn't necessary withnew
. However,new
can be used in a way it won't throw expections, as when functionset_new_handler
is set
- Because malloc doesn't throw exceptions, you have to check its result against
malloc
andfree
do not call object constructors and destructors, since there is no objects inC
.- see this question and this post.
Why does replacing malloc() require knowledge of the linker but ::operator new() does not?
Standard C++ makes provisions for overriding ::operator new
. While the implementation is certainly messy and linker-related, a C++ program can just define a different ::operator new
and it works. The C++ standard explicitly says: Programs can replace these with their own definitions (etc. etc. various restrictions and details).
malloc
on the other hand is an ordinary function defined in an ordinary library, and C (and C++, for that matter) has no facilities for replacing a function like that. You can convince virtually every linker under the sun to link to your libc
sans malloc
and resolve references to malloc
to some code from another library/object file. But you can't just define a different malloc
functions since that violates the one-definition rule: You end up with two functions called "malloc" in the program, which is both prohibited by the standard (for non-static
, non-anonymous-namespace
, non-inline
, ... functions) and a serious problem for linkers (most likely, an error or one of the two definitions is dropped).
Difference between 'new operator' and 'operator new'?
I usually try to phrase things differently to differentiate between the two a bit better, but it's a good question in any case.
Operator new is a function that allocates raw memory -- at least conceptually, it's not much different from malloc()
. Though it's fairly unusual unless you're writing something like your own container, you can call operator new directly, like:
char *x = static_cast<char *>(operator new(100));
It's also possible to overload operator new either globally, or for a specific class. IIRC, the signature is:
void *operator new(size_t);
Of course, if you overload an operator new (either global or for a class), you'll also want/need to overload the matching operator delete as well. For what it's worth, there's also a separate operator new[] that's used to allocate memory for arrays -- but you're almost certainly better off ignoring that whole mess completely.
The new operator is what you normally use to create an object from the free store:
my_class *x = new my_class(0);
The difference between the two is that operator new just allocates raw memory, nothing else. The new operator starts by using operator new to allocate memory, but then it invokes the constructor for the right type of object, so the result is a real live object created in that memory. If that object contains any other objects (either embedded or as base classes) those constructors as invoked as well.
What is the difference between new/delete and malloc/free?
new
/ delete
- Allocate / release memory
- Memory allocated from 'Free Store'.
- Returns a fully typed pointer.
new
(standard version) never returns aNULL
(will throw on failure).- Are called with Type-ID (compiler calculates the size).
- Has a version explicitly to handle arrays.
- Reallocating (to get more space) not handled intuitively (because of copy constructor).
- Whether they call
malloc
/free
is implementation defined. - Can add a new memory allocator to deal with low memory (
std::set_new_handler
). operator new
/operator delete
can be overridden legally.- Constructor / destructor used to initialize / destroy the object.
malloc
/ free
- Allocate / release memory
- Memory allocated from 'Heap'.
- Returns a
void*
. - Returns
NULL
on failure. - Must specify the size required in bytes.
- Allocating array requires manual calculation of space.
- Reallocating larger chunk of memory simple (no copy constructor to worry about).
- They will NOT call
new
/delete
. - No way to splice user code into the allocation sequence to help with low memory.
malloc
/free
can NOT be overridden legally.
Table comparison of the features:
Feature | new / delete | malloc / free |
---|---|---|
Memory allocated from | 'Free Store' | 'Heap' |
Returns | Fully typed pointer | void* |
On failure | Throws (never returns NULL ) | Returns NULL |
Required size | Calculated by compiler | Must be specified in bytes |
Handling arrays | Has an explicit version | Requires manual calculations |
Reallocating | Not handled intuitively | Simple (no copy constructor) |
Call of reverse | Implementation defined | No |
Low memory cases | Can add a new memory allocator | Not handled by user code |
Overridable | Yes | No |
Use of constructor / destructor | Yes | No |
Malloc vs New for Primitives
Never use malloc
in C++. Never use new
unless you are implementing a low-level memory management primitive.
The recommendation is:
Ask yourself: "do I need dynamic memory allocation?". A lot of times you might not need it - prefer values to pointers and try to use the stack.
If you do need dynamic memory allocation, ask yourself "who will own the allocated memory/object?".
If you only need a single owner (which is very likely), you should
usestd::unique_ptr
. It is a zero cost abstraction overnew
/delete
. (A different deallocator can be specified.)If you need shared ownership, you should use
std::shared_ptr
. This is not a zero cost abstraction, as it uses atomic operations and an extra "control block" to keep track of all the owners.
If you are dealing with arrays in particular, the Standard Library provides two powerful and safe abstractions that do not require any manual memory management:
std::array<T, N>
: a fixed array ofN
elements of typeT
.std::vector<T>
: a resizable array of elements of typeT
.
std::array
and std::vector
should cover 99% of your "array needs".
One more important thing: the Standard Library provides the std::make_unique
and std::make_shared
which should always be used to create smart pointer instances. There are a few good reasons:
Shorter - no need to repeat the
T
(e.g.std::unique_ptr<T>{new T}
), no need to usenew
.More exception safe. They prevent a potential memory leak caused by the lack of a well-defined order of evaluation in function calls. E.g.
f(std::shared_ptr<int>(new int(42)), g())
Could be evaluated in this order:
new int(42)
g()
- ...
If
g()
throws, theint
is leaked.More efficient (in terms of run-time speed). This only applies to
std::make_shared
- using it instead ofstd::shared_ptr
directly allows the implementation to perform a single allocation both for the object and for the control block.
You can find more information in this question.
Related Topics
Best Way to Start a Thread as a Member of a C++ Class
Best Way to Do Variant Visitation with Lambdas
Treat C Cstyle Array as Std::Array
How to Force Gcc to Link Unreferenced, Static C++ Objects from a Library
This Case of Template Function Overloading Eludes My Understanding
How to Overload a Function That Can Tell a Fixed Array from a Pointer
Why Use a "Tpp" File When Implementing Templated Functions and Classes Defined in a Header
What Is the Best Solution to Pause and Resume Pthreads
C++11 Variadic Printf Performance
Why Is Cmake Designed So That It Removes Runtime Path When Installing
Decltype, Result_Of, or Typeof