If you manage memory manually, it’s your responsibility to delete all memory created with new, and to make sure it’s
deleted once and only once. Ensuring this is done is error-prone, especially when your function can have early exit points.
Fortunately, the C++ language provides tools that automatically manage memory for you. Using them systematically makes the code simpler and more
robust without sacrificing performance.
This rule raises an issue when you use:
-
new - you should prefer a factory function that returns a smart pointer, such as std::make_unique or, if shared
ownership is required, std::make_shared,
-
new[] - you should prefer a container class, such as std::vector,
-
delete or delete[] - if you followed the previous advice, there is no need to manually release memory.
If your compiler does not support make_unique, it’s easy to write your own:
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
Noncompliant code example
void f() {
auto c = new Circle(0, 0, 5);
c->draw();
delete c;
}
Compliant solution
void f() {
auto c = make_unique<Circle>(0, 0, 5);
c->draw();
unique_ptr<Circle> c2{new Circle(0, 0, 5)}; // Clumsy, but still compliant by exception
}
Exceptions
If the result of a new is immediately passed as an argument to a function, we assume that the function takes ownership of the newly created object,
and won’t raise an issue.