The careful handling of resources - may it be for example memory, files or sockets - is a key concern of programming in C++. This holds in particular true for the embedded programming that is often characterized by limited resources. Therefore, I will write a few posts about this challenging and versatile topic.
In my first attempt to write this post I wanted to directly jump into the memory allocation with operator new. Fortunately, I went a few steps back. Memory management is only one but admittedly an import component of resource management in C++. The story is a lot more versatile. So I want to write about three domains of resource management in C++.
There is the automatic memory management in C++ that is quite easy to use. I addition we have the well known idioms in C++ that are the base of the automatic memory management. At last C++ offers explicit memory management in which the user has the full power to his disposal. I will follow this three steps in my post. Because I don't want to create the impression that explicit memory management is basic knowledge for the C++ developer.
Automatic memory management
I start at the basic level with smart pointers.
C++ has four different smart pointers. Each of them has the task to take care of the lifetime of it underlying resource. The std::unique_ptr takes explicitly ownership of the lifetime of one resource. A std::shared_ptr shares the ownership of a resource with the other std::shared_ptr's. Therefore, cycles can appear and the resource can not automatically be released. It's the job of the std::weak_ptr to break these cycles. The last one is the with C++11 deprecated std::auto_ptr. Why? You will see in a later post.
STL container cont like std::vector or std::string automatically manage their memory. E.g.: they have a method cont.push_back to add a new element to the container. The size of the container will automatically grow. But it works also the other way around. Thanks to cont.shrink_to_fit, the container will be reduced to its size.
Each modern STL implementations uses the C++ idioms move semantic, perfect forwarding, and the RAII idiom very often. To understand the underlying mechanism we have to dig deeper in the details of the automatic memory management. Before I write about the C++ idioms here is a small appetizer.
The key idea of move semantic is quite simple: use cheap move operations instead of expensive copy operations for big objects. This holds in particular true for such objects that can not be copied. A typical example is a std::mutex or a std::unique_ptr.
Perfect forwarding uses under the hood similar techniques like the move semantic. The key idea of perfect forwarding is a different one. The job of perfect forwarding is it to take arguments in a function template and forward them identically. Typical use case are constructors that forward their argument to the base class constructor or factory methods which creates new objects.
The idea of the RAII idiom is quite simple. You bind the acquisition and the release of a resource to the lifetime of a local object. Therefore, the resource will automatically be initialized in the constructor and released in the destructor. The acronym RAII stand for Resource Acquisition Is Initialization. Smart pointer and locks implement this technique.
Explicit memory management
Now we are in the domain of the experts. Thanks to the explicit memory management in C++ it is possible the tailor memory management to your needs. You can adjust it to simple objects or arrays, but you can also adjust it on a class level or global level. You can write your own memory allocators and use them with the help of placement new.
As promised I will write about the various flavours of memory management in C++ from top to bottom. I start in the next post with the automatic memory management with smart pointers.
Go to Leanpub/cpplibrary "What every professional C++ programmer should know about the C++ standard library". Get your e-book. Support my blog.