I know the free operation in C is to tell the compiler this particular memory block is free for compiler to use for further allocation, but the memory is not released.
What about the delete in C++? the same as free?
I know the free operation in C is to tell the compiler this particular memory block is free for compiler to use for further allocation, but the memory is not released.
What about the delete in C++? the same as free?
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);
delete
is the same (ish) as free
, but has important differences. The most notable difference is that delete
will run an objects destructor whereas free
won't.
As the comments point out, another very important detail is not mixing malloc/free and new/delete. If you allocate with malloc, use free and similarly if you use new, use delete!
They are not the same. The delete
operator in C++ calls the object's destructor, which, depending on the implementation, should release the memory. The delete
function can also be overloaded, where free
cannot.
malloc() and free() are not to be used in C++ code because they don't support object semantics. Furthermore, the results of calling free() to release an object that was allocated by new, or of using delete to release memory that was allocated by malloc(), are undefined. The C++ standard doesn't guarantee that the underlying implementation of operator new uses malloc(); in fact, on some implementations malloc() and new use different heaps. Check this link
delete() would delete the entire memory space occupied making it imposible to refer the varaiable once its gets deleted where in free() u could still access it.