The pointer to implementation or PIMPL idiom is a popular C++ idiom for decoupling the representation and implementation of a class. It reduces compilation times and enables a stable API while allowing the internals to change.

Reference counting is another ubiquitous programming technique, used to manage an object’s lifetime by keeping track of the number of references held to it. C++’s std::shared_ptr uses this technique to provide shared ownership of an object through a pointer.

We can easily combine these two techniques to create an object that shares the benefits of both. It suffices to replace the std::unique_ptr which is commonly used to implement the PIMPL idiom with a std::shared_ptr. Doing so makes the implementation even simpler: we can rely on the compiler-generated destructor, copy/move-constructor and copy/move-assignment operator. By relying on std::shared_ptr for the reference counting implementation, we get robust and well-tested behavior with a minimal amount of code to maintain.

Starting from the excellent implementation of the PIMPL idiom on, the code below illustrates what a reference-counted PIMPL implementation would look like.

// Based on

// foo.h - header file
#include <memory>

class foo {

  class impl;
  std::shared_ptr<impl> pimpl;

// foo.cpp - implementation file
class foo::impl {
  void do_internal_work() { internal_data = 5; }

  int internal_data = 0;

foo::foo() : pimpl{std::make_shared<impl>()} { pimpl->do_internal_work(); }

Both techniques incur some overhead, although very minimal. Whether this outweighs the simplicity of its design is a trade-off you’ll have to consider for yourself.