Preface
Programs regularly have to allocate and manage memory, no matter what programming language they are written in. Why and how we do this depends on the language and the application domain, however: real-time systems, embedded systems, games, and conventional desktop applications all have different needs and constraints, and there is no single, universal best approach to all problems.
This book shows how modern C++ lets programmers write simpler and safer programs, but also how that language makes it possible to take control of memory allocation mechanisms and make sure programs respect the constraints they face. Starting from the language's basic concepts of objects' lifetimes and memory organization, you will learn how to write your own containers and your own allocators, and to adapt the very behavior of allocation operators to suit your needs. Depending on your needs, you will be able to make programs that are smaller, faster, more predictable... and safer.
Who this book is for
This book is written for individuals who have some programming experience and who enjoy both high-level and low-level programming. Having prior experience with generic programming and concurrent programming will lead to a more pleasant reading experience.
More specifically, this book is written for you if (a) you think managing memory in C++ is difficult but are willing to take a fresh look at it, (b) you want better control over the way your programs manage memory, or (c) you want your programs to be smaller, faster, and safer. You might benefit from this book if you come from a C++ background, of course, but also if you normally program in other languages and would like to look at what C++ allows you to do. This book will be helpful to any programmer, but you might find it particularly useful if you program in constrained environments (such as embedded systems or game consoles) or in other application domains where you need tight control over resource allocation mechanisms. Who knows, you might even enjoy it!
What this book covers
Chapter 1, Objects, Pointers, and References, discusses the basic concepts of the object model in the C++ language, providing us with a common basic vocabulary.
Chapter 2, Things to Be Careful With, looks at some of the tricky aspects of C++, with a more specific examination of low-level programming maneuvers that can lead us into trouble; we will examine what kind of trouble these can lead us to.
Chapter 3, Casts and cv-qualifications, examines the tools at our disposal to coerce the type system to our needs and discusses how to use these sometimes sharp tools in reasonable ways.
Chapter 4, Using Destructors, looks at this important aspect of C++ that makes it possible to write objects that are responsible for the management of resources in general and of memory in particular.
Chapter 5, Using Standard Smart Pointers, provides a look at how we can benefit from this important part of contemporary C++ programming, which inscribes responsibility over memory into the type system.
Chapter 6, Writing Smart Pointers, looks at ways in which we write homemade versions of the standard smart pointers as well as how we can design our own smart pointers to cover niches that are not yet covered by those provided by the standard library.
Chapter 7, Overloading Memory Allocation Operators, shows some of the many ways in which we can provide our own versions of memory allocation operators and explains why it can be a good idea to do so.
Chapter 8, Writing a Naïve Leak Detector, puts our new memory management skills to use to write a working (if simple) tool to detect memory leaks in a way that is essentially transparent to user code.
Chapter 9, Atypical Allocation Mechanisms, takes a tour of some unusual applications (and overloads) of the standard memory allocation operators, including non-throwing versions and others that handle "exotic" memory.
Chapter 10, Arena-Based Memory Management and Other Optimizations, uses our memory management skills to make programs execute more quickly and behave more deterministically, benefitting from domain-specific or application-specific knowledge.
Chapter 11, Deferred Reclamation, explores ways in which we can write programs that automatically reclaim dynamically allocated objects at chosen moments during program execution.
Chapter 12, Writing Generic Containers with Explicit Memory Management, explains how to write two efficient generic containers that manage memory themselves and discusses exception-safety and complexity tradeoffs of this practice.
Chapter 13, Writing Generic Containers with Implicit Memory Management, revisits the containers written in the previous chapter to see the impacts of moving from an explicit memory management approach to an implicit one that relies on smart pointers.
Chapter 14, Writing Generic Containers with Allocator Support, revisits our homemade containers to see how memory management can be customized through allocators, covering allocators from before C++11 to contemporary allocators, as well as PMR allocators.
Chapter 15, Contemporary Issues, looks toward the near future and examines some recent (as of the book's writing) features of C++ that pertain to memory management as well as some interesting candidate additions to the language in C++26 and C++29.
Annexure: Things You Should Know, provides some technical background that can help you get the most out of this book but that might not be common knowledge. Refer to it as needed, it's there for you!
To get the most out of this book
You will need a contemporary C++ compiler, ideally one that supports at least C++20 and ideally C++23. This book does not require other tools, but you are of course welcome to use your favorite code editor and experiment with the examples you will meet as you progress.
Care was taken to keep to standard C++ from a portable and safe perspective. The few places where you will meet examples that use non-portable code are identified as such.
Code examples have been tested on three distinct compilers and the samples on the book's GitHub repository all contain, in addition to the actual source code, links to online versions (in comments) that compile and that you can modify and adapt as you wish.
If you are using the digital version of this book, we advise you to type the code yourself or access the code from the book's GitHub repository (a link is available in the next section). Doing so will help you avoid any potential errors related to the copying and pasting of code.
I hope you enjoy the experience and find the examples to be an interesting starting point for your own explorations.
Download the example code files
You can download the example code files for this book from GitHub at https://github.com/PacktPublishing/C-Plus-Plus-Memory-Management. If there's an update to the code, it will be updated in the GitHub repository.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
Conventions used
There are a number of text conventions used throughout this book.
Code in text: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "The whole body of f() could legitimately be rewritten by your compiler as return g(*p) in this case, with the return *p statement being turned into unreachable code."
A block of code is set as follows:
int g(int); int f(int *p) { if(p != nullptr) return g(*p); // Ok, we know p is not null return *p; // oops, if p == nullptr this is UB }
When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:
class X { public:
// #0 delegates to #1 which delegates to #0 which... X(float x) : X{ static_cast<int>(x) } {
// #0 }
Any command-line input or output is written as follows:
Verbose(0) Verbose(2) Verbose(6) Verbose(7)
Tips or important notes
Appear like this.
Get in touch
Feedback from our readers is...