C++ Core Guidelines: Rules to Resource Management


This and the next posts will probably be about the most important concern in programming: resource management. The C++ Core Guidelines has rules for resource management in general but also rules for allocation and deallocation and smart pointers in particular. Today I will begin with the general rules of resource management.


photo montage 1548599 640

At first. What is a resource? A resource is something that you have to manage. That means you have to acquire and release it because resources are limited or you have to protect them. You can only have a limited amount of memory, sockets, processes or threads; only one process can write a shared file or one thread can write a shared variable at one point in time. If you don't follow the protocol, a lot of issues are possible.

Your system may

  • become out of memory because you leak memory.
  • have a data race because you forget to acquire a lock before you use the shared variable.
  • have a deadlock because you are acquiring and release a few shared variables in a different sequence.

The issues with data race and data locks are not unique to shared variables. For example, you can have the same issues with files.

If you think about resource management it all boils down to one key point: ownership. So let me give you first the big picture before I write about the rules.

What I like in particular about modern C++, is, that we can directly express our intention about ownership in code.

  • Local objects. The C++ runtime as the owner automatically manages the lifetime of these resources. The same holds for global objects or members of a class. The guidelines call them scoped objects.
  • References: I'm not the owner. I only borrowed the resource that cannot be empty.
  • Raw pointers: I'm not the owner. I only borrowed the resource that can be can be empty. I must not delete the resource.
  • std::unique_ptr: I'm the exclusive owner of the resource. I may explicitly release the resource.
  • std::shared_ptr: I share the resource with other shared ptr. I may explicitly release my shared ownership.
  • std::weak_ptr: I'm not the owner of the resource but I may become temporary the shared owner of the resource by using the method std::weak_ptr::lock.

Compare this fine-grained ownership semantic to just a raw pointer. Now you know, what I like about modern C++.

Here is the summary of the rules to resource management.

Let's look at each of them in detail.

R.1: Manage resources automatically using resource handles and RAII (Resource Acquisition Is Initialization)

The idea is quite simple. You create a kind of proxy object for your resource. The constructor of the proxy will acquire the resource and the destructor will release the resource. The key idea of RAII is that the C++ runtime is the owner of the local object and therefore of the resource.

Two typical examples for RAII in modern C++ are smart pointers and locks. Smart pointer takes care of their memory and locks take care of their mutexes.

The following class ResourceGuard models RAII.

// raii.cpp

#include <iostream>
#include <new>
#include <string>

class ResourceGuard{
    const std::string resource;
    ResourceGuard(const std::string& res):resource(res){
      std::cout << "Acquire the " << resource << "." <<  std::endl;
      std::cout << "Release the "<< resource << "." << std::endl;

int main(){

  std::cout << std::endl;

  ResourceGuard resGuard1{"memoryBlock1"};                  // (1)

  std::cout << "\nBefore local scope" << std::endl;
    ResourceGuard resGuard2{"memoryBlock2"};                // (2)
  std::cout << "After local scope" << std::endl;
  std::cout << std::endl;

  std::cout << "\nBefore try-catch block" << std::endl;
      ResourceGuard resGuard3{"memoryBlock3"};              // (3)
      throw std::bad_alloc();
  catch (std::bad_alloc& e){
      std::cout << e.what();
  std::cout << "\nAfter try-catch block" << std::endl;
  std::cout << std::endl;



It makes no difference, if the lifetime of instances of ResourceGuard ends regularly (1) and (2) or irregularly (3). The destructor of ResourceGuard will always be called. This means the resource will be released.


If you want to know more details about the example and RAII, read my post: Garbage Collection - No Thanks. Even Bjarne Stroustrup made a comment.

R.2: In interfaces, use raw pointers to denote individual objects (only)

Raw pointers should not denote arrays because this is very error-prone. This becomes, in particular, true if your function takes a pointer as an argument.

void f(int* p, int n)   // n is the number of elements in p[]
    // ...
    p[2] = 7;   // bad: subscript raw pointer
    // ...


It's quite easy to pass the wrong side of the array as an argument.

For arrays, we have containers such as std::vector. A container of the Standard Template Library is an exclusive owner. It acquires and releases it's memory automatically.

R.3: A raw pointer (a T*) is non-owning

The issue of ownership becomes in particular interesting if you have a factory. A factory is a special function that returns a new object. Now the question is. Should you return a raw pointer, an object, a std::unique_ptr, or a std::shared_ptr?

Here are the four variations:

Widget* makeWidget(int n){                    // (1)
    auto p = new Widget{n};
    // ...
    return p;

Widget makeWidget(int n){                     // (2)
    Widget g{n};
    // ...
    return g;

std::unique_ptr<Widget> makeWidget(int n){    // (3)
    auto u = std::make_unique<Widget>(n);
    // ...
   return u;

std::shared_ptr<Widget> makeWidget(int n){    // (4)
    auto s = std::make_shared<Widget>(n);
    // ...
   return s;


auto widget = makeWidget(10);


Who should be the owner of the widget? The caller or the callee? I assume you can not answer the question for the pointer in the example. Me too. This means we have not idea who should call delete. In contrast, cases (2) to (4) are quite obvious. In the case of the object or of the std::unique_ptr, the caller is the owner. In the case of the std::shared_ptr, the caller and the callee share the ownership.

One question remains. Should you go with an object or a smart pointer. Here are my thoughts.

  • If your factory must be polymorphic such as a virtual constructor, you have to use a smart pointer. I have already written about this special use case. Read the details in the post: C++ Core Guidelines: Constructors (C.50).
  • If the object is cheap to copy and the caller should be the owner of the widget, use an object. If not cheap to copy, use a std::unique_ptr.
  • If the callee wants to manage the lifetime of the widget, use a std::shared_ptr

R.4: A raw reference (a T&) is non-owning

There is nothing to add. A raw reference is non-owning and cannot be empty.

R.5: Prefer scoped objects, don’t heap-allocate unnecessarily

A scoped object is an object with its own scope. That may be a local object, a global object, or a member. The C++ runtime takes care of the object. There is no memory allocation and deallocation involved and we can not get a std::bad_alloc exception. To make it simple. If possible, use a scoped object.

R.6: Avoid non-const global variables

I often hear: global variables are bad. That is not totally true. Non-const global variables are bad. There are many reasons for avoiding non-const global variables. Here are a few reasons. I assume for simplicity reasons that the functions or objects use non-const global variables.

  • Encapsulation: Functions or objects could be changed outside of their scope. This means it is quite difficult to think about your code.
  • Testability: You can not test your function in isolation. The effect of your function depends on the state of your program.
  • Refactoring: It's quite difficult to refactor your code if you can not think about your function in isolation.
  • Optimisation: You can not easily rearrange the function invocations or perform the function invocations on different threads because there may be hidden dependencies.
  • Concurrency: The necessary condition for having a data race is a shared, mutable state. Non-const global variables are shared mutable state.

What's next?

In the next post, I will write about a very important resource: memory.



Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, Marko, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, espkk, Louis St-Amour, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Neil Wang, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Tobi Heideman, Daniel Hufschläger, Red Trip, Alexander Schwarz, Tornike Porchxidze, Alessandro Pezzato, Evangelos Denaxas, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Dimitrov Tsvetomir, Leo Goodstadt, Eduardo Velasquez, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, and Michael Young.


Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, and Bhushan Ivatury.



My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small



I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

Bookable (Online)


Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.


Contact Me

Modernes C++,





Tags: memory

My Newest E-Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Interactive Course: The All-in-One Guide to C++20

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code


Today 1938

Yesterday 7541

Week 24864

Month 194281

All 7462121

Currently are 174 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments