Details of unique_ptr instance in C++11 smart Pointers

  • 2020-09-16 07:43:06
  • OfStack

In the previous article, we looked at 1, shared_ptr and weak_ptr introduced in C++11. Today, we will introduce 1, another smart pointer, unique_ptr.

References of previous articles:

[C++11 new feature] C++11 smart pointer shared_ptr

C++11 New feature C++11 Smart pointer weak_ptr

unique_ptr introduction

unique is unique and unique, hence the name magic, unique_ptr can "exclusively" own the object it points to, it provides a strict sense of ownership.

This 1 point is very different from the shared_ptr pointer we introduced earlier: shared_ptr allows multiple Pointers to the same object, whereas unique_ptr can only have one pointer to that object at a time.

unique_ptr holds a pointer to an object and automatically releases the resources it points to when it is deleted or leaves its scope.

1. How to create unique_ptr

unique_ptr does not have the standard library function make_shared as shared_ptr1 does to create one instance of shared_ptr.

To create 1 unique_ptr, we need to pass the pointer returned by 1 new operator to the constructor of unique_ptr.

Example:


int main() {
 //  create 1 a unique_ptr The instance 
 unique_ptr<int> pInt(new int(5));
 cout << *pInt;
}

2. Unable to perform copy construction and assignment

unique_ptr does not have an copy constructor and does not support normal copy and assignment operations.

Example:


int main() {
 //  create 1 a unique_ptr The instance 
 unique_ptr<int> pInt(new int(5));
 unique_ptr<int> pInt2(pInt); //  An error 
 unique_ptr<int> pInt3 = pInt; //  An error 
}

3. Move construction and move assignment can be performed

While unique_ptr does not support normal copy and assignment operations, it does provide a movement mechanism to transfer ownership of Pointers from 1 unique_ptr to another unique_ptr.

If you need to transfer ownership, you can use the std::move() function.

Example:


int main() {
 unique_ptr<int> pInt(new int(5));
 unique_ptr<int> pInt2 = std::move(pInt); //  Transfer of ownership 
 //cout << *pInt << endl; //  Make a mistake, pInt Is empty 
 cout << *pInt2 << endl;
 unique_ptr<int> pInt3(std::move(pInt2));
}

4. unique_ptr can be returned

unique_ptr does not support copy operations, with one exception: you can return 1 unique_ptr from a function.

Example:


unique_ptr<int> clone(int p)
{
 unique_ptr<int> pInt(new int(p));
 return pInt; //  return unique_ptr
}

int main() {
 int p = 5;
 unique_ptr<int> ret = clone(p);
 cout << *ret << endl;
}

unique_ptr Usage scenario

1. Provide abnormal security guarantee for dynamically applied resources

Let's take a look at the following code:


void Func()
{
 int *p = new int(5);

 // ... (An exception may be thrown) 

 delete p;
}

This is our traditional way of writing it: when we dynamically request memory, it is possible that our next code does not perform the delete operation due to an exception thrown or an early exit (if statement).

The solution is to use unique_ptr to manage dynamic memory, and whenever the unique_ptr pointer is created successfully, its destructor is called. Ensure that dynamic resources are released.


void Func()
{
 unique_ptr<int> p(new int(5));

 // ... (An exception may be thrown) 
}

2, return the function to dynamically apply the ownership of resources

Examples are as follows:


unique_ptr<int> Func(int p)
{
 unique_ptr<int> pInt(new int(p));
 return pInt; //  return unique_ptr
}

int main() {
 int p = 5;
 unique_ptr<int> ret = Func(p);
 cout << *ret << endl;
 //  When the function is finished, the resource is automatically released 
}

3. Save the pointer in the container


int main() {
 vector<unique_ptr<int>> vec;
 unique_ptr<int> p(new int(5));
 vec.push_back(std::move(p)); //  Using mobile semantics 
}

4. Manage dynamic arrays

The standard library provides a version of unique_ptr for managing dynamic arrays.


int main() {
 unique_ptr<int[]> p(new int[5] {1, 2, 3, 4, 5});
 p[0] = 0; //  Reload the operator[]
}

conclusion


Related articles: