C++ smart pointers

The difference between C++ smart pointers
Introduction: There are four smart pointers in C++: auto_ptr, shared_ptr, weak_ptr, unique_ptr The latter three are supported by c++11, and the first one has been deprecated by 11.

What is the role of smart pointers?
The role of smart pointers is to manage a pointer.

Why use smart pointers?
When the allocated space is forgotten to be released at the end of the function, it will cause a memory leak. The smart pointer is a class. When it exceeds the scope of the class, the class will automatically call the destructor, and the destructor will automatically release resources. Therefore, the smart pointer will automatically release the memory space at the end of the function, and there is no need to manually release the memory space, thus avoiding memory leaks.


1. The ownership model adopted by auto_ptr (the scheme of c++98, which has been abandoned by cpp11)

Example of use:

/*int型*/
int*p=new int(0);
auto_ptr<int> ap(p);

/*结构体*/
struct A {
    
    
  void f();
}
auto_ptr<A>apa(new A);
apa->f();

Points to note about errors:
1. Because of the ownership model adopted, one radish has one pit, and two auto_ptrs cannot own the same object at the same time. E.g:

int*p=new int(0);
auto_ptr<int>ap1(p);
auto_ptr<int>ap2(p);

At this time, both ap1 and ap2 think that the ownership of the pointer p belongs to them, and both try to delete p when destructing. The behavior of deleting the same object twice is undefined in the C++ standard. So we have to prevent using auto_ptr like this.

2. Because the destructor of auto_ptr uses delete instead of delete[], we should not use auto_ptr to manage an array pointer.

int*pa=new int[10];
auto_ptr<int>ap(pa);

3. When the smart pointer is deprived of ownership, it will report an error when it is used again

int*p=new int(0);
auto_ptr<int>ap1(p);
auto_ptr<int>ap2=ap1;
cout<<*ap1;//错误,此时ap1只剩一个null指针在手了

void f(auto_ptr<int>ap) {
    
    
    cout<<*ap;
} 
auto_ptr<int>ap1(new int(0));
f(ap1);
cout<<*ap1;//错误,经过f(ap1)函数调用,ap1已经不再拥有任何对象了。

Summary: When using the auto_ptr pointer, you need to pay attention to one thing. An auto_ptr pointer can only have one object. At the same time, be careful not to continue to use it after being deprived of ownership.

2. unique_ptr (replaces auto_ptr)
Compared with auto_ptr, unique_ptr has stricter requirements and implements the concept of exclusive ownership or strict ownership.

int*p=new int(0);
auto_ptr<int>ap1(p);
auto_ptr<int>ap2 = ap1; //此时不会报错
cout << *ap1;  //报错

int *p=new int(0);
unique_ptr<int>ap1(p);
unique_ptr<int>ap2=ap1;  //报错

/*若想做到auto_ptr*/
int *p=new int(0);
unique_ptr<int>ap1(p);
unique_ptr<int>ap2=std::move(ap1); //move转移拥有权

3. shared_ptr
shared_ptr realizes the concept of shared ownership. Multiple smart pointers can point to the same object, and the object and its associated resources will be released when the "last reference is destroyed". A counting mechanism is used to indicate that a resource is shared by several pointers. You can view the number of resource owners through the member function use_count().

Member function:

use_count Returns the number of reference counts
unique Returns whether it is exclusive ownership ( use_count is 1)
swap Swap two shared_ptr objects (that is, exchange owned objects)
reset Give up the ownership of the internal object or the change of the owned object, which will cause the original object The decrement of the reference count
get returns the inner object (pointer)
using the instance:

#include <iostream>
#include <memory>
using namespace std;
class A {
    
    
public:    
int i;    
A(int n):i(n) {
    
     };    
~A() {
    
     cout << i << " " << "destructed" << endl; }
};
int main() {
    
        
    shared_ptr<A> sp1(new A(2)); //A(2)由sp1托管,
    shared_ptr<A> sp2(sp1);      //A(2)同时交由sp2托管    
    shared_ptr<A> sp3;    
    sp3 = sp2;   //A(2)同时交由sp3托管    
    cout << sp1->i << "," << sp2->i <<"," << sp3->i << endl;    
    A * p = sp3.get();      // get返回托管的指针,p 指向 A(2)    
    cout << p->i << endl;   //输出 2    
    sp1.reset(new A(3));    // reset导致托管新的指针, 此时sp1托管A(3)    
    sp2.reset(new A(4));    // sp2托管A(4)    
    cout << sp1->i << endl; //输出 3    
    sp3.reset(new A(5));    // sp3托管A(5),A(2)无人托管,被delete
    cout << "end" << endl;    
    return 0}

Four: weak_ptr
weak_ptr is a smart pointer that does not control the life cycle of the object, pointing to an object managed by a shared_ptr. The purpose of weak_ptr design is to cooperate with shared_ptr to introduce a smart pointer to assist shared_ptr work. It can only be constructed from a shared_ptr or another weak_ptr object, and its construction and destruction will not cause the reference count to increase or decrease. Weak_ptr is used to solve the deadlock problem when shared_ptr refers to each other. If two shared_ptrs refer to each other, the reference count of these two pointers can never drop to 0, and the resource will never be released. It is a weak reference to the object, does not increase the reference count of the object, and can be converted to shared_ptr. Shared_ptr can be directly assigned to it. It can obtain shared_ptr by calling the lock function.
Example of use:

/*share_ptr死锁问题,导致计数不为0*/
class B;
class A {
    
    
  public:
  shared_ptr<B> pb_;
  ~A() {
    
    
    cout<<"A delete\n";
  }
};
class B {
    
    
  public:
  shared_ptr<A> pa_;
  ~B() {
    
    
    cout<<"B delete\n";
  }
};
void fun() {
    
    
  shared_ptr<B> pb(new B());
  shared_ptr<A> pa(new A());
  pb->pa_ = pa;
  pa->pb_ = pb;
  cout<<pb.use_count()<<endl;
  cout<<pa.use_count()<<endl;
}
int main() {
    
    
  fun();
  return 0;
}

/*修改,将share_ptr互相引用换成weak_ptr,避免死锁问题*/
class B;
class A {
    
    
  public:
  weak_ptr<B> pb_;
  ~A() {
    
    
    cout<<"A delete\n";
  }
};
class B {
    
    
  public:
  weak_ptr<A> pa_;
  ~B() {
    
    
    cout<<"B delete\n";
  }
};
void fun() {
    
    
  shared_ptr<B> pb(new B());
  shared_ptr<A> pa(new A());
  pb->pa_ = pa;
  pa->pb_ = pb;
  cout<<pb.use_count()<<endl;
  cout<<pa.use_count()<<endl;
}
int main() {
    
    
  fun();
  return 0;
}

Note: If you cannot directly access the object through weak_ptr, you must first convert weak_ptr to shared_ptr.
Reprinted: https://blog.csdn.net/yxh_1_/article/details/109000184

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324103766&siteId=291194637