Skip to main content

Item 17: Store newed objects in smart pointers in standalone statements

Concept

If you combine a new expression with other operations in a single statement, an exception thrown between the new and the smart pointer construction can lead to a resource leak. C++ compilers have flexibility in the order they evaluate function arguments, so a call like processWidget(std::shared_ptr<Widget>(new Widget), priority()) could leak if priority() throws between the new and the shared_ptr construction. The fix is to store the newed object in a smart pointer in its own standalone statement.

Code Example

#include <memory>

class Widget { /* ... */ };
int priority() { return 1; }
void processWidget(std::shared_ptr<Widget> pw, int prio) { /* ... */ }

void problematic() {
// DANGEROUS: potential resource leak!
// If priority() is called between new Widget and shared_ptr ctor,
// and priority() throws, the Widget is leaked.
processWidget(std::shared_ptr<Widget>(new Widget), priority());
}

void safe() {
// SAFE: standalone statement ensures no leak
std::shared_ptr<Widget> pw(new Widget);
processWidget(pw, priority());

// Even better in C++14+: use make_shared
processWidget(std::make_shared<Widget>(), priority());
}

Full source code

Things to Remember

  • Store newed objects in smart pointers in standalone statements. Failure to do this can lead to subtle resource leaks when exceptions are thrown.
  • Prefer std::make_shared and std::make_unique (C++14) which avoid this problem entirely.
  • Item 13 — RAII and smart pointers for resource management
  • Item 29 — Exception safety
  • Item 18 — Making interfaces easy to use correctly