The differences between free in C and delete in C+

2019-04-10 14:13发布

问题:

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?

回答1:

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);


回答2:

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!



回答3:

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.



回答4:

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.