文章目录
前言
一、智能指针的原理
1、RAII机制
RAII(Resource Acquisition is Initialization),即【资源获取即初始化】,也就是说在构造函数中申请分配资源,在析构函数中释放资源。因为C++的语言机制保证了,当一个对象创建的时候,自动调用构造函数,当对象超出作用域的时候会自动调用析构函数。所以,在RAII的指导下,我们应该使用类来管理资源,将资源和对象的生命周期绑定。
智能指针就是RAII最具代表的实现之一。使用智能指针,可以实现自动的内存管理,再也不需要担心忘记delete造成的内存泄漏。毫不夸张的来讲,有了智能指针,代码中几乎不需要再出现delete了。
2、简单的实现
在了解了RAII机制之后,我们可以尝试实现一个简单的智能指针。
#include <iostream>
using namespace std;
/*RAII技术被认为是C++中管理资源的最佳方法,
进一步引申,使用RAII技术也可以实现安全、
简洁的状态管理,编写出优雅的异常安全的代码。*/
template<class T>
class Smart_ptr
{
private:
T* m_p;
public:
//调用构造函数时,申请资源
Smart_ptr(T* p = nullptr):m_p(p)
{
cout << "constructor ptr" << endl;
}
//调用析构函数时,自动释放资源
~Smart_ptr()
{
if(m_p)
{
cout << "delete ptr" << endl;
delete m_p;
}
}
//普通指针的功能
//通过重载运算符使其拥有和普通指针一样的功能
T& operator*()const {
return *m_p;}
T* operator->()const {
return m_p;}
};
在上述代码中,我们利用RAII机制,实现了智能指针自动释放资源,又通过重载了operator*和operator->,使其具有和指针一样的行为和功能。
我们可以通过以下的测试用例,观察RAII机制下的智能指针的工作情况:
struct AA
{
int m_a;
AA(int a = 0):m_a(a){
cout << "constructor AA" << endl;}
~AA(){
cout << "destructor AA" << endl;}
};
int main()
{
//语句块方便观察析构函数的调用
//指向自定义类型的对象
{
AA* pa = new AA;
Smart_ptr<AA> sp1(pa);
cout << sp1->m_a << endl;
}
//指向自定义类型的匿名对象
{
Smart_ptr<AA> sp2(new AA(5));
cout << sp2->m_a << endl;
}
//指向内置类型的对象
{
Smart_ptr<int> sp3(new int(5));
cout << (*sp3) << endl;
}
return 0;
}
运行结果:
constructor AA
constructor ptr
0
delete ptr
destructor AA
constructor AA
constructor ptr
5
delete ptr
destructor AA
constructor ptr
5
delete ptr
二、智能指针的用法
1、智能指针的分类
在C++11中,提供了三种智能指针,接下来我们来逐一了解。使用这些智能指针时需要引用头文件< memory>。
- std::shared_ptr:共享的智能指针
- std::unique_ptr:独占的智能指针
- std::weak_ptr:弱引用的智能指针,它不共享指针,不能操作资源,是用来监视shared_ptr的。
(在C++11之前还有auto_ptr,但由于它并非安全的所以本文不作介绍)
2、unique_ptr
unique_ptr独享它指向的对象,也就是说,同时只有一个unique_ptr指向同一个对象,当这个unique_ptr被销毁时,指向的对象也随即被销毁。
以下是unique_ptr的声明:
template <typename T, typename D = default_delete<T>>//第二个模板参数D:指定删除器,缺省用delete释放资源
class unique_ptr
{