2 points why unique_ptr should be preferred
In this post we will see three cases where using unique_ptr will make the program more secure and faster.
Link :C++ unique_ptr
First:: Sure deallocation with unique_ptr.
If you have read the post on shared_ptr of this tutorial, this exact same topic is discussed there. Well, using unique_ptr too is secure in this matter. Consider, that a function returns an address of a dynamic storage. If on the calling side if the caller forgets to delete the storage then there will be a memory leakage.
int* func( ) { int *i=new int(90) ; … //Do anything here return i; }
If the caller is responsible enough to delete the storage then the program is secure. But still, there is a situation in which the region containing the deleting code is never reached. This case happens if somewhere in the middle an exception is thrown. When an exception is thrown, the program will terminate and the remaining code is never executed.Consider the functions below.
int* func( ) { int *i=new int(90) ; … ///Do anything here return i ; } void Count( int i ) { i=890; //… throw(90) ; //exception thrown here } void TestFunc( ) { int *newMem=returnIntPtr( ); Count( newMem ) ; //throws exception delete newMem ; //never executed }
If the function Count( newMem ) throws an exception the ‘delete newMem’ is never called.And so there is a memory leakage. But if unique_ptr is used instead of the raw pointer there should be no issue here even if an exception is thrown. The unique_ptr will make sure that the storage is deleted during run-time, this means even in the midst of untimely ending of program execution you can sit back and relax.
int* func( ) { int *i=new int(90) ; … ///Do anything here return i ; } void Count( int i ) { i=890; ///… throw(90) ; //exception thrown here } void TestFunc( ) { unique_ptr<int>up=static_cast<unique_ptr<int>>( func( ) ) ; Count( *up ) ; ///throws exception }
Now the address returned by func( ) is assigned to unique_ptr, so here if count() throws an exception the memory will still be deleted safely.
Using unique_ptr instead of raw pointer as a data member of a class
Suppose you have a class in which one of the data members should be a pointer and it must handle a dynamic storage. Well, you can make that pointer a raw pointer and in the destructor, you can add the deleting code. Such a design is safe because the destructor is called every time the object goes out of scope. However, it is safer and more efficient if the pointer used is unique_ptr instead of the raw pointer.
class A { int *i ; public: A(int *ii=nullptr ):i(ii) { } ~A( ) { delete i; } } ; //Using unique_ptr class A { unique_ptr<int>i ; public: A(int *ii=nullptr ):i(static_cast<unique_ptr<int>>(ii) ) { } ~A( ) { } }; int main( ) { A a(new int(90) ) ; //Declaring object,works fine for both the A class shown above return 0; }
Using unique_ptr prevent the need for adding a storage deleting code in the destructor. And if there are more than one pointers, there is no need to trouble yourself by not forgetting to add a deleting code for each of them. The another property introduced in your class by unique_ptr is the objects are not shareable.
int main( ) { A a(new int(67) ) , a1 ; a1=a ; //error not shareable return 0 ; }
Calling a copy constructor is also not allowed because copying means sharing the object. However, you can make the object moveable and this process is faster than sharing the object because the object is simply moved and there is no need for creating a new storage and copy the value. But to make the object moveable you must add a move assignment operator to the class and how this is done is shown below.
class A { unique_ptr<int>i ; public: A(int *ii=nullptr ):i(static_cast<unique_ptr<int>>(ii) ) { } A& operator=(A &&m ) noexcept { if(this== &m ) { return *this ; } up=std::move(m.up); m.up=nullptr ; return *this ; } ~A( ) { } }; int main( ) { A a( new int(89) ) , a1 ; a1=a; //error not shareable a1=std::move(a) ; //works fine return 0 ; }
Now you can move the object and note (I am repeating it again) moving the object is faster than copying the object.