C++智能指针

文章目录

  • 一、智能指针的目的和基本原理
  • 二、不带引用计数的智能指针
      • 2.1 auto_ptr
      • 2.2 scoped_ptr
      • 2.3 unique_ptr
  • 三、带引用计数的智能指针
      • 3.1 shared_ptr
      • 3.2 weak_ptr


一、智能指针的目的和基本原理

一般new出来的对象会用普通指针引用,此时申请的堆上的资源需要我们手动使用delete进行资源释放。如果忘记delete或者delete之前程序出现未可预知的意外,之前申请的资源就不能正常释放,造成内存泄露;
 
智能指针是对裸指针(普通指针)的封装,智能指针利用了栈上对象在跳出作用域会自动析构的原理,让智能指针去管理资源。所以智能指针对象一般不能new。
 

二、不带引用计数的智能指针

2.1 auto_ptr

auto_ptr只能管理一个对象,如果使用拷贝构造函数进行auto_ptr初始化,

#include "iostream"
#include "string"

using namespace std;

int main() {
    auto_ptr<int> p1(new int(10));
    auto_ptr<int> p2(p1); 
    *p1 = 20; //此处会出现问题,因为把对象的控制权转让给了p2,之前的p1底层会自动指向nullptr
    return 0;
}

C++智能指针_第1张图片
auto_ptr已经过期,如上的这种问题导致C++并不建议使用auto_ptr。
 

2.2 scoped_ptr

基于以上auto_ptr的问题,scoped_ptr直接禁止使用拷贝构造函数和赋值重载运算符函数。scoped_ptr部分源码如下所示:

template<class T> class scoped_ptr // noncopyable
{
private:
    T * px;
	
    scoped_ptr(scoped_ptr const &);
    scoped_ptr & operator=(scoped_ptr const &);
 
    typedef scoped_ptr<T> this_type;
		
	//以下两个函数直接被删除,禁止使用
    void operator==( scoped_ptr const& ) const;
    void operator!=( scoped_ptr const& ) const;

 

2.3 unique_ptr

从名字就可以看出来unique_ptr只能管理一个资源。
而且unique_ptr也删除了拷贝构造函数和赋值运算符重载函数。
但是unique_ptr提供了一个带右值引用的拷贝构造函数和赋值运算符重载函数,使用方法如下所示:

// 示例1
unique_ptr<int> ptr(new int);
//如下相当于把对象的控制权从ptr转给了ptr2
unique_ptr<int> ptr2 = std::move(ptr); // 使用了右值引用的拷贝构造
ptr2 = std::move(ptr); // 使用了右值引用的operator=赋值重载函数

 

三、带引用计数的智能指针

 

3.1 shared_ptr

如名字所示,多个智能指针对象指向同一个内存资源,智能指针对象里维护了一个引用计数器对象,表示当前指针指向的对象被多少个智能指针引用。当引用计数减到0的时候才真正的进行对象的析构。
shared_ptr维护的计数器对象是在new在堆上的,
shared_ptr又叫做强智能指针。
 

3.2 weak_ptr

C++智能指针_第2张图片
如上的情况叫做交叉引用,A对象和B对象的引用计数都是2,如果使用shared_ptr,如果ptrA或者ptrB不再引用对象,对象本应该被释放,但是实际上引用计数不为0,对象不能被释放,这种情况就要使用weak_ptr。
 
弱智能指针weak_ptr区别于shared_ptr之处在于:

1、weak_ptr不会改变资源的引用计数,只是一个观察者的角色,通过观察shared_ptr来判定资源是否存在
2、weak_ptr持有的引用计数,不是资源的引用计数,而是同一个资源的观察者的计数
3、weak_ptr没有提供常用的指针操作,无法直接访问资源,需要先通过lock方法提升为shared_ptr强智能指针,才能访问资源。
 
从shared_ptr和weak_ptr之间的区别可以看出,在对象内部引用其他对象的时候使用weak_ptr,外部的时候使用shared_ptr。

你可能感兴趣的:(coding,c++)