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;