In this article, we are going to learn about one of the smart pointers in C++, the unique pointers which we denote as unique_ptr. We will learn what is unique pointer in C++ and how is it used, how we create unique pointers and where we should use them, where we should not use them.
So let us begin with what are unique pointers.
What is Unique_ptr in C++ and how it is used
Unique_ptr is the most easy and commonly used pointer type in smart pointers. This is very similar to normal old style pointers when it comes to its use. of course it is much more smarter than the old style pointers. If you want to use a smart pointer and not sure which one to use then start with unique_ptr.
unique_ptr points to a unique pointer or you can say memory address. The address it points to can not be pointed by any other pointer.
It is unique in itself in the whole system memory. That address is reserved only for unique pointer(until unless is freed and reused by means like move()). This also means that you can not create a copy of this pointer. But it offer one flexibility, that you can pass this pointer to another pointer by using move() semantics. In this case the old pointer will no longer stay valid and new pointer will be in control of this address now.
How to create and use unique_ptr in C++
The syntax to create a unique pointer is:
unique_ptr NameofPointer(new Data Type);
or
unique_ptr NameofPointer
Where:
unique_ptr : This is the syntax to specify that we are creating a unique_ptr of a specified Data Type. We are passing the Data
Types in the <> brackets. It can be a standard data type like int , float or a user defined data type like a class, structure etc.
NameofPointer : This is the Name of the pointer variable that you want to give it to. (new Data Type) : This is the memory allocation done by using the new operator and the data type so the proper size can be allocated on heap same as the size of data type.
Now let us see this unique_ptr in some code examples. The first thing to keep in mind is we must include the <memory>
header file to get the unique_ptr declaration in our program.
unique_ptr C++ example
#include <iostream>
#include <memory>
using namespace std;
void Pointer_function()
{
// Declaration of a unique_ptr of type int with a int raw pointer.
unique_ptr<int> ptr(new int(63));
if(ptr)
{
cout<< " This is a unique_ptr pointer of type int";
}
// Declaration of a unique_ptr which is empty.
unique_ptr<int> empty_ptr;
if(empty_ptr == nullptr)
{
cout<< " This is a null or empty pointer of type int";
}
}
int main()
{
Pointer_function();
return 0;
}
In this example code, we are first declaraing a unique_ptr of type int and we are passing a raw pointer of type int as argument.
second declaration that we are doing is also a unique_ptr, but this time we didn’t not pass any argument so it will create an empty unique_ptr which is not pointing to any memory.
As soon as the Pointer_function() ends(both smooth exit or exception exit), both the pointers will go out of scope and any memory associated with them will be deleted and freed. This is done by the destructor of the unique_ptr which does this clean up for us.
So we don’t need to do explicit memory clean up when we use the smart pointers.
Unique_ptr can not be copied
unique_ptr object can not be copied As we mentioned in the definition of unique_ptr,unique_ptr can not be copied or assigned to another objects. So if you will try to make use of a copy constructor or assignment operator, it will fail.
unique_ptr<int> ptr(new int(63));
std::unique_ptr<int> copyPtr = ptr; // fail with error at compile time
copyPtr = ptr; // fail with error at compile time
Unique_ptr objects can be moved
As we just saw above that unique_ptr can not be copied,so is it a worry? No! They can not be copied but they can be moved. When we say moved, it means we can transfer the ownership of the memory address to another unique_ptr variable. This can be done by using the move semantics or move() function.
Here is an code example doing this:
unique_ptr<int> ptr(new int(63));
if(ptr != nullptr)
std::unique_ptr<int> newPtr = std::move(ptr);
else
cout << "Your pointer is null so cant be moved";
if(ptr != nullptr)
cout << "Your move did not work";
else
cout << "Your move was successful!";
If you see , we are checking ptr again after the move, why? Because we are verifying the move is successfully done and this can be guaranteed if ptr is nullptr. It is nullptr after move because now the new owner of the address is newPtr.