the Chromium logo

The Chromium Projects

Smart Pointer Guidelines

What are smart pointers?

Smart pointers are a specific kind of "scoping object". They are like regular pointers but can automatically deallocate the object they point to when they go out of scope. Since C++ is not a garbage collected language, such functionality is important. The pattern where scoping objects are used to automatically manage the lifetime of heap-allocated objects is called RAII - Resource Acquisition Is Initialization.

Here's some sample use of std::unique_ptr<>, the most common type of smart pointer:

// We can put a pointer into a std::unique_ptr<> at construction time...
std::unique_ptr value(base::JSONReader::Read(data));
std::unique_ptr foo_ptr(new Foo(...));

// ...or by using reset().
std::unique_ptr bar_ptr;      // Like "Bar* bar_ptr = nullptr;".
bar_ptr.reset(new Bar(...));  // Now |bar_ptr| is non-nullptr and owns the object.

// We can test the std::unique_ptr<> directly.
if (!value)
  return false;

// get() accesses the raw pointer underneath.
Foo* raw_ptr = foo_ptr.get();

// We can call through the std::unique_ptr<> as if it were a raw pointer.
DictionaryValue* dict;
if (!value->GetAsDictionary(&dict))
  return false;

Why do we use them?

Smart pointers ensure we properly destroy an object even if its creation and destruction are widely separated. They make functions simpler and safer by ensuring that no matter how many different exit paths exist, local objects are always cleaned up correctly. They help enforce that exactly one object owns another object at any given time, preventing both leaks and double-frees. Finally, their use clarifies ownership transference expectations at function calls.

What types of smart pointers exist?

The two common smart pointers in Chromium are std::unique_ptr<> and scoped_refptr<>. The former is used for singly-owned objects, while the latter is used for reference-counted objects (though normally you should avoid these -- see below). If you're familiar with C++11, scoped_refptr<> is similar in intent to std::shared_ptr<> (Note: the latter is banned).

base/memory/ has a few other objects of interest:

When do we use each smart pointer?

What are the calling conventions involving different kinds of pointers?

See the calling conventions section of the Chromium style guide for the rules; some common cases are illustrated below.

What about passing or returning a smart pointer by reference?

Don't do this.

In principle, passing a const std::unique_ptr<T>& to a function which does not take ownership has some advantages over passing a T*: the caller can't accidentally pass in something utterly bogus (e.g. an int converted to a T*), and the caller is forced to guarantee the lifetime of the object persists across the function call. However, this declaration also forces callers to heap-allocate the objects in question, even if they could otherwise have declared them on the stack. Passing such arguments as raw pointers decouples the ownership issue from the allocation issue, so that the function is merely expressing a preference about the former. For the sake of simplicity and consistency, we avoid asking authors to balance these tradeoffs, and simply say to always use raw pointers.

One exception is lambda functions used with STL algorithms operating on containers of smart pointers; these may have to take e.g. const std::unique_ptr<T>& in order to compile. And speaking of that...

I want to use an STL container to hold pointers. Can I use smart pointers?

Yes! As of C++11, you can store smart pointers in STL containers.

General references on smart pointers