malloc() and free() do not support construction and destruction, and do not mix well with new and delete.
In some implementations that delete and that free() might work, or maybe they will cause run-time errors.
R.11: Avoid calling new and delete explicitly
The pointer returned by new should belong to a resource handle (that can call delete).
If the pointer returned by new is assigned to a plain/naked pointer, the object can be leaked.
In a large program, a naked delete (that is a delete in application code, rather than part of code devoted to resource management) is a likely bug: if you have N deletes, how can you be certain that you don't need N+1 or N-1?
The bug might be latent: it might emerge only during maintenance. If you have a naked new, you probably need a naked delete somewhere, so you probably have a bug.
R.12: Immediately give the result of an explicit resource allocation to a manager object
If you don't, an exception or a return might lead to a leak.
voidf(const string& name){
FILE* f =fopen(name,"r");// open the file
vector<char>buf(1024);// The allocation of buf might fail and leak the file handle.auto _ =finally([f]{fclose(f);});// remember to close the file ... but what if above throw already...// ...}// instead...voidf(const string& name){
ifstream f{name};// open the file with RAII already
vector<char>buf(1024);// ...}
R.13: Perform at most one explicit resource allocation in a single expression statement
If you perform two explicit resource allocations in one statement, you could leak resources because the order of evaluation of many subexpressions, including function arguments, is unspecified.
voidfun(shared_ptr<Widget> sp1, shared_ptr<Widget> sp2);// someone could have done this ...fun(shared_ptr<Widget>(newWidget(a, b)),shared_ptr<Widget>(newWidget(c, d)));// BAD: potential leak
This is exception-unsafe because the compiler might reorder the two expressions building the function's two arguments.
In particular, the compiler can interleave execution of the two expressions: Memory allocation (by calling operator new) could be done first for both objects, followed by attempts to call the two Widget constructors.
If one of the constructor calls throws an exception, then the other object's memory will never be released!
This subtle problem has a simple solution: Never perform more than one explicit resource allocation in a single expression statement.
For example:
shared_ptr<Widget>sp1(newWidget(a, b));// Better, but messyfun(sp1,newWidget(c, d));
The best solution is to avoid explicit allocation entirely use factory functions that return owning objects:
fun(make_shared<Widget>(a, b),make_shared<Widget>(c, d));// Best
Write your own factory wrapper if there is not one already.
R.14: Avoid [] parameters, prefer span
An array decays to a pointer, thereby losing its size, opening the opportunity for range errors.
Use span to preserve size information.
voidf(int[]);// not recommendedvoidf(int*);// not recommended for multiple objects// (a pointer should point to a single object, do not subscript)voidf(gsl::span<int>);// good, recommended