shared_ptr智能指针

本文详细介绍了C++中智能指针shared_ptr的使用,包括构造、复制、移动以及析构等操作,并探讨了其内部引用计数的工作机制。此外,还讲解了weak_ptr的作用,如何通过它来避免对象的悬挂引用问题。通过示例代码展示了shared_ptr和weak_ptr的使用方法,以及如何确保内存管理的正确性。
摘要由CSDN通过智能技术生成

1. shared_ptr智能指针

  • shared_ptr智能指针对一个对象采用共享所有权的机制来管理其生命周期,当对象的引用计数变为了0时shared_ptr才会析构其管理的对象
  • 一个shared_ptr的大小是裸指针的两倍,因为其内部包含了两个指针,一个指向该对象的裸指针,另一个是指向该对象的引用计数的裸指针

1.1 通过一个示例简单了解shared_ptr的基本用法

#include <iostream>
#include <memory>

using namespace std;

class Dog
{
public:
  Dog() { cout << "dog ctor...\n"; }
  ~Dog() { cout << "dog dtor...\n"; }
};

int main()
{
#define show_use_count(p)                                  \
  do                                                       \
  {                                                        \
    cout << #p << " use count: " << p.use_count() << endl; \
  } while (0)

  Dog *rawPtr = new Dog();           /* 原始指针 */
  shared_ptr<Dog> sharedPtr(rawPtr); /* 将一个裸指针作为入参传入shared_ptr的构造函数,rawPtr申请的堆区内存将由sharedPtr负责释放 */
  show_use_count(sharedPtr);         /* 此时sharedPtr的引用计数为1 */

  cout << "\ncopy ctor...\n";
  shared_ptr<Dog> copyPtr(sharedPtr); /* 复制构造函数, 注意这里入参不能再传入rawPtr,否则会导致对rawPtr指向的内存二次释放 */
  /* 此时sharedPtr、copyPtr的引用计数变为2 */
  show_use_count(sharedPtr);
  show_use_count(copyPtr);

  cout << "\nmove ctor...\n";
  shared_ptr<Dog> movePtr(std::move(copyPtr)); /* 移动构造函数 */
  /* 此时sharedPtr、movePtr的引用计数变为2. copyPtr的引用计数变为0, 并被置为空 */
  show_use_count(sharedPtr);
  show_use_count(copyPtr);
  show_use_count(movePtr);
  
  if (copyPtr) { cout << "copyPtr is not null...\n"; } /* operator bool()成员函数,用来返回一个shared_ptr是否为空 */
  else { cout << "copytPtr is null...\n"; }

  /* 自定义释放规则 */
  cout << "\nset delete function...\n";
  shared_ptr<Dog> arrPtr(new Dog[3], [](Dog *p) { cout << "delete dog array...\n"; delete [] p; });

  return 0;
}
g++ a.cpp  -fsanitize=leak 

通过加上-fsanitize=leak编译运行上面的代码,可以发现没有产生内存泄漏,在main函数结束的时候shared_ptr析构了new出来的Dog对象

1.2 成员函数

  • swap
void std::shared_ptr::swap (shared_ptr& x) noexcept   

交换两个相同类型shared_ptr指向对象的内容。

  • reset
void reset() noexcept;
template <class U> void reset (U* p);
template <class U, class D> void reset (U* p, D del);
template <class U, class D, class Alloc> void reset (U* p, D del, Alloc alloc);

当该不传入任何参数时,rese会把shared_ptr指向的引用计数减少1,然后将该shared_ptr置空。当给reset传入一个新申请的堆内存地址时,该shared_ptr会指向该堆内存,并将引用计数初始值设为1

  • get
element_type* get() const noexcept;

获得 shared_ptr 对象内部包含的裸指针

  • use_count
long int use_count() const noexcept;

返回shared_ptr所值对象当前的引用计数

  • unique
bool unique() const noexcept;

判断shared_ptr所值对象当前的引用计数是否为1

1.3 std::enable_shared_from_this

std::enable_shared_from_this是一个模板类,并且以派生类作为模板类型的实参。一个类,通过继承enable_shared_from_this,就能得到一个指向其自身的shared_ptr指针

class Dog : public std::enable_shared_from_this<Dog>
{
public:
  Dog() { cout << "dog ctor...\n"; }
  ~Dog() { cout << "dog dtor...\n"; }
  shared_ptr<Dog> get_shared_ptr() { return this->shared_from_this(); }
};

2. weak_ptr智能指针

weak_ptr可以看做是shared_ptr的一种扩充。weak_ptr同样能够共享对象的所有权,但是确不会增加引用计数。weak_ptr一个最重要的作用是用来判断其指向的对象是否存在。通过调用weak_ptr的lock成员函数,如果其指向的对象不存在,则返回一个空指针,否则返回一个指向该对象的shared_ptr

shared_ptr<element_type> std::weak_ptr::lock() const noexcept;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值