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 |
Why use malloc/free, when we have new/delete?
They're not the same. new
calls the constructor, malloc
just allocates the memory.
Also, it's undefined behavior mixing the two (i.e. using new
with free
and malloc
with delete
).
In C++, you're supposed to use new
and delete
, malloc
and free
are there for compatibility reasons with C.
malloc and free vs new and delete
new
calls a constructor, malloc()
does not. delete
calls a destructor, free()
does not. If the class in question allocates memory internally, then yes, you are likely to encounter a memory leak.
If you have to use malloc()
and free()
(and in C++, you really shouldn't be), you will have to use placement new to call the constructor, and call the destructor yourself, eg:
pStr = static_cast<String*>(malloc(4 * sizeof(String)));
if (pStr)
{
for (int i = 0; i < 4; ++i)
new (&pStr[i]) String;
...
for (int i = 3; i >= 0; --i)
pStr[i].~String();
free(pStr);
}
And if you really need to mimic new[]
, you should handle exceptions thrown by constructors, eg:
pStr = static_cast<String*>(malloc(4 * sizeof(String)));
if (!pStr)
throw std::bad_alloc("");
int numConstructed = 0;
try
{
for (int i = 0; i < 4; ++i)
{
new (&pStr[i]) String;
++numConstructed;
}
}
catch (const std::exception &)
{
for (int i = numConstructed-1; i >= 0; ++i)
pStr[i]).~String();
throw;
}
...
for (int i = numConstructed-1; i >= 0; --i)
pStr[i].~String();
free(pStr);
In C++, what is the difference between new and new[] for array allocations
Some clever implementations of malloc don't actually keep track of the size per allocation (by clever use of rounding up), thus it have extremely low space overhead. They'll allocate a large block of memory, and anytime a dev allocates <64 bytes, it'll just use the next 64 bytes of this block, and mark a single bit elsewhere that tracks that this block of 64 bytes is now in use. Even if the user only wants to allocate 1 byte, it hands out a whole block. This means each allocation has only a single bit overhead, so every 8 allocations has a shared byte of overhead. Practically nothing. (There are far smarter strategies than this, this is just a simplified example)
new
and delete
can share this super-low-overhead implementation, because delete
knows to always destroy one object, regardless of the amount of space it actually has. This is again, super fast, and has low space overhead.
delete[]
can't do that because it has to know exactly how many destructors to call. So it has to keep track of how many items are in the array, up to std::size_t
, which means ~4 bytes have to be added to every new[]
. If the data requires an alignment >4, then each allocation also has to have wasted padding bytes between the count and the first item in the array. And delete[]
therefore has to know how to look past the padding, find the count, so it knows exactly how many objects to destroy. This takes both time and more space, for every allocation.
C++ gives you the choice between "always works, but slower and bigger", and "only works for one item, but faster and smaller", so the program can run as fast as possible.
malloc/free and new/delete compatibility in C++?
Yes, you can interleave them - just use a deallocation function matching the one used for allocation. The problem only arises if you use a wrong deallocation function.
Note that it's not that easy when you have several libraries - those might use different heaps and so even though you use a right named function it might happen to be implemented in the wrong module and so use the wrong heap which will drive you right into undefined behavior. See this answer for a better idea of what I'm talking about here.
What is the difference between new and malloc and calloc in C++? [duplicate]
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++.
malloc
allocates uninitialized memory. The allocated memory has to be released withfree
.calloc
is likemalloc
but initializes the allocated memory with a constant (0). It needs to be freed withfree
.new
initializes the allocated memory by calling the constructor (if it's an object). Memory allocated withnew
should 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.
Why are new()/delete() slower than malloc()/free()?
Look at this piece of C code:
struct data* pd = malloc(sizeof(struct data));
init_data(pd);
The new
operator in C++ is essentially doing what the above piece of code does. That's why it is slower than malloc()
.
Likewise with delete
. It's doing the equivalent of this:
deinit_data(pd);
free(pd);
If the constructors and destructors are empty (like for built-ins), new
and delete
shouldn't be slower than malloc()
and free()
are. (If they are, it's often due to the fact that common implementations call malloc()
/free()
under the hood, so they are a wrapper around them. Wrapping costs. Also, there might be code that needs to find out that no constructors/destructors are to be called. That would cost, too.)
Edit To answer your additional question:
new
and delete
aren't functions, they are operators. This: new data()
is called a new expression. It does two things. First it calls the operator new
, then it initializes the object, usually by invoking the appropriate constructor. (I say "usually" because built-ins don't have constructors. But a new expression involving a built-in works the same nevertheless.)
You can manipulate both of these phases. You can create your own constructors to manipulate initialization of your types and you can overload operator new
(even with several overloads having different additional arguments and also specifically for each class, if you want) in order to manipulate allocation of free storage. If you don't implement your own operator new
, the version from the standard library is used. A common implementation of this calls malloc()
.
Likewise, if you write delete pd
, called a delete expression, two things happen: depending on pd
, the object is de-initialized, usually by calling its destructor, then the memory is released by calling the appropriate operator delete
.
Again, you can manipulate both phase, by writing your own destructor, and by writing your own version of operator delete
. (The version of operator delete
that comes with your standard library is often implemented to call free()
.)
The differences between free in C and delete in C++?
There are two notions of delete
in C++: One is the operator, declared as ::operator delete(void*)
, which basically only frees up the memory and isn't usually thought about by most programmers. The other is the delete expression, delete p;
, where p
is a T*
. The expression invokes the destructor of the object pointed to by p
(and then frees the memory), which is a crucial language feature of C++ that has no analogue in C.
As a rule of thumb, you pair new
expressions with delete
expressions, and malloc()
function calls with free()
function calls:
T * p = new T; // constructor called!
delete p; // destructor called!
void * x = malloc(5); // just raw memory
free(x); // freed
Advanced part (not in response to the OP's question)
Dynamic object lifetime in C++ follows this general pattern: Allocate, construct, destroy, deallocate. The standard new
expression performs allocation and construction, while the standard delete
expression performs destruction and deallocation.
You could write out the process manually:
T * p = (T*)::operator new(sizeof(T)); // allocate raw memory
p = new (p) T; // call the constructor ("placement new")
/*...*/
p->~T(); // destroy the object
::operator delete(p); // deallocate the memory
In fact, if you really wanted to implement Baby's First C++, you could define the operators as just as malloc
/free
:
void * operator new(size_t n) { return malloc(n); }
void operator delete(void * p) { free(p); }
The real C++ magic happens by virtue of the new
and delete
expressions: The standard new
expression invokes the constructor (a new
expression is the only way to call a constructor in C++!) after allocation, while the standard delete expression invokes the destructor before deallocation.
Why "standard expression"? Well, you can also define and overload many other versions of new
and delete
operators. However, there is an important asymmetry: While you can use a custom new
operator in a custom new
expression (generally dubbed "placement new"), there is no equivalent "placement-delete" expression. So whenever you use a custom new
expression, you have to manually invoke the destructor before calling the matching custom delete operator:
T * p = new (A, B, C) T; // some custom new expression
// Entirely equivalent version:
T * p = (T*) ::operator new(sizeof(T), A, B, C); // this is your custom overload
T * p = new (p) T; // std. placement-new expression calls constructor
/* ---- later ---- */
p->~T(); // Must destroy manually!
::operator delete(p, A, B, C); // your matching custom overload
Note that there does not exist a custom delete expression delete (A,B,C) p'
!
For completeness, the standard placement new operator, whose only purpose is to call a constructor, is mandated by the standard to take the following form:
void * operator new(size_t, void * p) { return p; }
It's matching delete
operator is also mandated, name to do nothing:
void operator delete(void * p, void *) { }
You can see in the above general example why this is necessary.
It is important always to overload custom versions of new
and delete
in pairs! The reason is that if the object construction fails with an exception inside the constructor, then the memory is released by a call to the delete
operator that matches the offending new
expression.
Second update: To be exception-safe, we have to consider that the constructor of T
might throw:
Version 1:
try {
T * p = new (A, B, C) T;
/* ... */
p->~T();
::operator delete(p, A, B, C); // automatically invoked if T::T() throws!
}
catch(...) { }
Version 2:
void * addr = ::operator new(sizeof(T), A, B, C);
try {
T * p = new (addr) T; // might throw
/* ... */
p->~T();
// ::operator delete(p, addr); // ditto as in (1), but does nothing
}
catch(...) { }
::operator delete(addr, A, B, C);
Related Topics
How to Implement Classic Sorting Algorithms in Modern C++
What Is the Proper Declaration of Main in C++
What Is "Rvalue Reference For *This"
What Are the Evaluation Order Guarantees Introduced by C++17
If You Shouldn't Throw Exceptions in a Destructor, How to Handle Errors in It
What Is External Linkage and Internal Linkage
Case-Insensitive String Comparison in C++
How to Print a Variable'S Type in Standard C++
Implicit Type Conversion Rules in C++ Operators
Overloading Friend Operator≪≪ For Template Class
C/C++ Maximum Stack Size of Program on Mainstream Oses
Running My C++ Code Gives Me a Blank Console
How to Call a Constructor from Another Constructor (Do Constructor Chaining) in C++
How to Serialize and Deserialize a Class in C++
Infinite Loop With Cin When Typing String While a Number Is Expected