Here we will discuss the C++ unique_ptr member functions: swap, release, reset. Some of its member functions are similar to shared_ptr while some other are specific to the unique_ptr. Since unique_ptr does not use reference counting method as it does not share its resources to other pointers, so the member function of shared_ptr that provides information related to reference counting such as use_count( ), unique( ), etc. is not included in the unique_ptr class.
Link :shared_ptr member functions
i)unique_ptr get( ) : This function return the raw addrss of the memory pointed by the
ii)unique_ptr swap( ) : This function swap the memory of the two unique_ptr.
The member functions found specifically in unique_ptr are:
ii)reset( ):This function is found in shared_ptr class but it does not accept two arguments.
Both of these functions are discussed in detail below.
i)release( ) member function
The purpose of release( ) function is to relinquish the ownership of the memory which the unique_ptr points to. This means if release( ) function is invoked the unique_ptr will no longer have the sole rights over the storage which it initially points to. After the unique_ptr losses the ownership over the storage an address of that storage is returned.Consider the code below.
unique_ptr<int*gt;up(new int(78) ); auto *newOwner=up.release( ) ; /*newOwner now owns the storage which holds the value 78 */ cout<< *up ; //undefined and dangerous cout<< *newOwner ; delete newOwner; //Do not forget
If release( ) function is called without assigning the returned address to any raw pointer or any other pointer then there is bound to be memory leakage.
unique_ptr<int>up(new int(09)) ; up.release( ) ; //memory leakage here
So whenever you call release() function do not forget to assign the return address to some other pointer that will handle the storage safely.
Since release() return a raw address there is another way of using it. When a new unique_ptr is created you can initialize this new unique_ptr to any existing unique_ptr using the release() function. In this case, the newly created unique_ptr will point to the storage of the unique_ptr of which the release() function was called. A code example is given below.
cout<< *upS ; //undefined and dangerous cout<< *upS1 ; //ok [/code]
upS1 now points to the storage containing the string “Wow!”.
ii)unique_ptr ‘reset’ member function
The purpose of reset( ) function vary depending on whether an argument is passed to it or not. You can call the reset() function either with no argument or by passing one argument. When a reset() function is called without passing any argument it’s purpose is to free the memory pointed by the unique_ptr .
unique_ptr<double> up(new double(90.346) ); up.reset( ) ; //frees the memory cout << *up ; //undefined and dangerous
After freeing the memory up will point to nullptr.
If an argument is passed to reset() function, then the argument must be an address of dynamic storage. In this case what happens is that the previous storage is deleted and the unique_ptr will point to the new storage whose address is passed as the argument.
unique_ptr<char>upC(new char(‘B’) ) ; upC.reset(new char(‘V’) ) ; cout<< *upC ;
upC now points to the new storage with the character ‘V’.
The argument required in reset() function is simply an address of the dynamic storage, so we can also use the return value of the release() function -which is an address of a dynamic storage- as the reset() function argument and call the function.Consider the code below.
unique_ptr<int>up(new int(89) ) , up1 ; up1.reset( up.release( ) ) ; cout<< *up1 ;
Whenever a release( ) function is called instead of assigning newly the storage to a built-in pointer, you can use the reset() function to assign the address to another unique_ptr just like we did above. This makes sure that the storage is in the secure hand, who knows assigning the storage to a raw pointer might just be another superfluous risk that you may be undertaking if something goes wrong; resulting to leakage of memory.
The unique_ptr has a sole right over the storage which it points to. And it does not share the ownership of the storage with any other pointer. This property of unique_ptr makes it unique and different from the shared_ptr. But then again if a reset() function is called upon a unique_ptr it loses its ownership rights and at times it is assigned the ownership of a new storage.
If reset() is used there is an exception in the behaviour of the unique_ptr. In other words, reset() function provides some flexibility in the behaviour of the unique_ptr.