[C++11] using C++11 to solve memory leakage -- smart pointer

As we all know, in c# and Java, developers do not need to release memory by themselves. After the object reference count is zero, the. Net and Java Virtual Opportunities automatically recycle objects to prevent memory leakage; However, in C + + language, the memory allocated on the heap must be managed by itself and released when not in use. If it is not managed properly, memory leakage may occur.

C++11 provides a smart pointer. After using the smart pointer, the user does not need to release the memory space. Once the object exceeds its own life cycle, it will be released automatically, so as to effectively solve the problem of memory leakage.

In actual programming, there are three kinds of smart pointers available: std::shared_ptr,std::unique_ptr and std::weak_ptr.

1. Shared smart pointer: std::shared_ptr

std::share_ Each copy of the PTR pointer points to the same object, and memory is released only when the reference count is zero.

The prototype of pointer declaration is:

template <class T> class shared_ptr;

1.1 std::shared_ Usage of PTR

std::shared_ptr pointer can be initialized by three methods: constructor, auxiliary function and reset method. The code is as follows:

int main () {
  std::shared_ptr<int> sp;
  sp.reset (new int);       //reset function initialization
  *sp=10;
  std::cout << *sp << '\n';
  
  std::shared_ptr<int> p(new int(1));//Constructor Initializers 
  std::cout<< *p << std::endl;
  std::shared_ptr<int> foo = std::make_shared<int> (20);
  std::cout<< *foo << std::endl;
  return 0;
}

The running result of the code is: 10 1 20

As can be seen from the above code, the use method of smart pointer is similar to that of ordinary pointer, but smart pointer does not need to manage memory by itself.

1.2 get original pointer

In the code, you can use the get method to obtain the original pointer, as shown in the code:

int main () {
  int* p = new int (10);
  std::shared_ptr<int> a (p);
  if (a.get()==p)
    std::cout << "a and p point to the same location\n";
  std::cout << *a.get() << "\n";
  std::cout << *a << "\n";
  std::cout << *p << "\n";
  return 0;
}

The above code tries to assign a common pointer to a smart pointer, and then judge whether the two pointers point to the same memory address. The operation results are as follows:

a and p point to the same location
10
10
10

1.3 specify pointer remover

The smart pointer can specify a delegator during initialization. When the pointer count is zero, the specified delegator will be called automatically to release the memory pointed to by the pointer. The delegator can be a function or a lambda expression, as shown in the code:

void DeletePoint(int *p){
    delete p;
}
int main(){
   std::shared_ptr<int> p(new int,DeletePoint);//Function method remover
   std::shsred_pte<int> p1(new int,[](int *p){delete p;});//expression
   return 0;
}

The above is an ordinary pointer. What should I do if I want to manage dynamic arrays with intelligent pointers? See the following code:

std::shared_ptr<int> p(new int[100],std::default_delete<int []>);

The above code uses std::default_delete, actually default_ The bottom layer of delete is still implemented by calling delete.

1.4 using STD:: shared_ Precautions for PTR

std::shared_ptr precautions are as follows:

  • Multiple STD:: shared cannot be initialized with the same raw pointer_ ptr
  • Do not create smart object pointers in function arguments, mainly because different compilers may have different conventions, and different call sequences may cause memory leakage. Therefore, you should create objects first and use them in the incoming function.
  • If the function wants to return this pointer, do not return this as a smart shared pointer. Because if two objects are constructed with the same pointer (this), the destruct may cause repeated destruct. The normal use method should be to inherit STD:: enable_ shared_ from_ This < T > class, and then return the pointer object of the base class.
  • Avoid circular references, which can lead to memory leaks.

2 exclusive smart pointer: std::unique_ptr

There are restrictions on the use of exclusive smart pointers, such as: other smart pointers are not allowed to share their internal pointers; Assignment of an exclusive pointer to another exclusive pointer is not allowed. If you want to assign an exclusive pointer to another exclusive pointer, there are two methods:

  • Return value through function;
  • Escape the ownership of the pointer object through the std::move method

The code is as follows:

  std::unique_ptr<T> p(new T);
  std::unique_ptr<T> p1 = std::move(p);

In C++ 11, make is not provided_ The unique function initializes the exclusive pointer, but a similar function is provided in C++14 to create a unique pointer_ PTR pointer object. Of course, we can also implement one ourselves. The implementation method is as follows:

template <class T,class ...Args> inline typename std::enable_if<!is_array<T>::value,
std::unique_ptr<T>>::type
make_unique(Args & ... args){
    return std::unique_ptr<T>(new T(std::foeward<Args>(args)...));
}

2.1 unique_ptr usage

The following code implements the assignment and use of exclusive pointers through the reset method:

int main () {
  std::unique_ptr<int> up;  
  up.reset (new int);      
  *up=5;
  std::cout << *up << '\n';
  up.reset (new int);      
  *up=10;
  std::cout << *up << '\n';
  up.reset();             
  return 0;
}

3 weak reference pointer: std::weak_ptr

Weak reference pointer is an assistant of shared pointer. Its main function is to monitor shared_ptr's life cycle, it can't manage resources, but it can use shared_ptr monitors resources. The construction and destruction of weak reference pointer itself will not modify the reference count. It is purely used as an assistant to monitor shared_ Whether PTR managed resources exist.

3.1 std::weak_ Basic usage of PTR

1) Through use_count gets the reference count of the current resource. The code is as follows:

int main(){
  std::shared_ptr<int>p(new int[10]);
  std::weak_ptr<int> wp(p);
  std::cout<<wp.use_count()<<std::endl;
  return 0;
}

The running result of the above code is: 1

2) Judge whether the resource has been released through the expired method

int main(){
  std::shared_ptr<int>p(new int[10]);
  std::weak_ptr<int> wp(p);
  p.reset();
  if(wp.expired()){
      std::cout<<"The monitor pointer has been released"<<std::endl;
  }else{
       std::cout<<"The monitoring pointer is valid"<<std::endl;
  }
  return 0;
}

The running result of the above code is that the monitoring pointer has been released.

It should be noted that the smart shared pointer can be released using the reset function.

3) Obtain the monitored shared through the lock method_ PTR resources

std::weak_ptr<int> wp;
void fun(){
     if(wp.expired()){
      std::cout<<"The monitor pointer has been released"<<std::endl;
  }else{
       auto p=wp.lock();
       std::cout<<*p<<std::endl;
  }
}

int main(){
  auto p = std::make_shared<int>(100);
  wp = p;
  fun();
  return 0;
}

The above code output is: 100

In addition to the functions described above, weak pointers are displayed in shared_ptr returns this pointer only by using weak pointer. Similarly, when solving the problem of circular reference, it only needs to use weak pointer for the members of any one of the two classes, and the problem of memory leakage caused by circular reference can be solved smoothly.

4 Summary

Smart pointer has become a sharp tool for C + + memory management tool to solve the problem of memory leakage. Although it is very helpful to us, we still need to be highly vigilant when using it to avoid more problems caused by improper use. When choosing to use smart pointer, you can refer to the following standards:

  • If you want only one pointer to manage resources or arrays, you can use the exclusive pointer: unique_ptr, on the contrary, if you want to manage with multiple pointers, you can use shared_ptr;
  • weak_ptr itself does not operate resources. It is only used for monitoring. It is used to solve shared problems_ PTR's this pointer return problem and circular reference counting problem. It's shared_ptr is a good assistant.

Posted on Tue, 16 Nov 2021 03:42:44 -0500 by digitalmarks