unique_ptr helps in automating memory management. A tool which helps to save us from the perils of memory leakage issues, ownership problems etc
If you look at a managed language like java, Garbage collector takes care of releasing the memory allocated in heap, so as a developer you never really need to worry about memory management. This is one of the top reasons, people from the other side of the world, especially java developers, would pick as the reason why coding in C++ is a dangerous job, where you need to take care of releasing the memory you allocated without GC
Coming back to unique ptr, it follows rather mysterious sounding RAII idiom( Resource Acquisition is Initialization) to automate memory management
When you initialize and create object for any class with a unique ptr, unique_ptr takes care of automatically executing destructor of the class, when the object goes out of scope
And the destructor of the class can have all the code to release resources and memory allocated in in constructor of the class
When using unique_ptr, our class will make use of value semantics, all the pointer dabbling is handled in unique_ptr implementation for us. This enables our code to be clean and neat
Consider a simple Widget class shown below which we'll make use for example,
// Example to demonstrate unique_ptr usage
#include <iostream>
#include <memory>
class Widget {
uint32_t value_;
public :
Widget(uint32_t value) : value_(value) {
std::cout << "Building Widget " << value_ << "\n";
}
~Widget() {
std::cout << "Destroying Widget " << value_ << "\n";
}
};
memory is the standard library include file for unique_ptr As explained above, while running the program, pay attention to the logs printed from constructor and destructor.
Now, when it comes to usage, see how do we allocate memory traditionally,
int main()
{
Widget* w = new Widget(1);
// Application
// Business
// Logic
delete w;
}
Next, we create a initialize a unique_ptr with Widget type, see we don't have any code from application side to deal with memory allocation and cleanup, everything is handled by unique_ptr for us, just like magic, except that there isn't really any magic, all the hard yards are covered by the standard library implementers for us, just so that, we can write clean and elegant code,
int main()
{
std::unique_ptr<Widget> uw = std::make_unique<Widget>(2);
}
You might be wondering what is that thing make_unique, it is a standard library helper function template available from C++14 which makes creating unique_ptr even more convenient, more on that later