smart_pointer
来源:互联网 发布:高德端口修改器 v33 编辑:程序博客网 时间:2024/06/05 21:59
引入:
C++程序员最痛苦的莫过于对内存管理,没有像C#和Java那样的内存回收机制,C++程序员在复杂的程序中容易造成内存泄漏,即便是程序员非常小心,异常的产生也会造成部分内存泄漏。(由于异常而导致delete语句没有释放动态分配的内存)从而引出了智能指针(smart_pointer)。
什么是智能呢?
这种指针实质是一个包装了一个指针的类,通过RAII机制来自动释放内存。下面会详细介绍RAII。通过在类里重载 * 运算符,和->运算符来实现基本指针的操作。
RAII(Resource Acqisition Is Initialzation)的缩写,也就是资源获取继初始化。是一种资源管理,避免内存泄漏的方法。RAII的做法是使用一个对象在构造时获取资源,在对象生命周期结束时自动调用析构函数来释放内存。
C++提供了基本的三种智能指针库里的(auto_ptr ,scoped_ptr)和C++11 boost库里的
shared_ptr.
下面来一一分析以下几个指针:
auto_ptr 第一代智能指针
template<class T>class Auto_ptr{public: Auto_ptr(T*p=0) :_ptr(p) {} ~Auto_ptr() { delete _ptr; _ptr = NULL; }T& operator *() { return *_ptr; }T* operator->(){ return _ptr;}T operator=(T&t){ *_ptr = t;}private: T *_ptr;};class my_struct{public: my_struct(int i=10,int j=20) :_i(i) , _j(j) {} int _i; int _j;};int main(){ Auto_ptr<int> p1(new int(3)); Auto_ptr<my_struct> p2(new my_struct);cout<<"*p1 = "<<*p1<<endl;cout << "p2->_i= "<<p2->_i<<endl;cout <<"p2->_j= "<< p2->_j<<endl;return 0;}
测试:
auto_ptr首先具有RAII也就是智能,也具有指针的普通操作。
但以上程序没介绍到赋值运算符重载 和拷贝构造。是因为auto_ptr的赋值运算符重载是一种管理权限转移的操作。如下图
要实现p1=p2,假设p1已经指向一块空间,那么就会让p2先指向这块空间,把p1至为空。也就是管理权限转变给了p2,这和我们的初心大相径庭。
而如果两个同时指向一块空间,析构的时候就会把原来的数据给丢失。所以auto_ptr是一个失败的例子。
scoped_ptr解决了auto_ptr的缺陷,也就是只给出了赋值运算符和拷贝构造的定义,并且为了防止恶意破坏,封装在private里。
template<class T>class scoped_ptr{public: scoped_ptr(T*p = 0) :_ptr(p) {} ~scoped_ptr() { delete _ptr; _ptr = NULL; } T& operator *() { return *_ptr; } T* operator->() { return _ptr; }private: scoped_ptr(scoped_ptr<T>& ptr); scoped_ptr<T>& operator=(scoped_ptr<T>& ptr); T *_ptr;};
最后C++提出了shared_ptr在boost库里,里面运用了引用计数的管理方法进行赋值,等操作。
template<class T>struct Delete{ void operator()(T* ptr) { delete ptr; }};template<class T>//定制的删除数组删除器struct DeleteArray{ void operator()(T* ptr) { delete[] ptr; }};template<class T, class D = Delete<T>>class SharedPtr{public: SharedPtr(T* ptr) :_ptr(ptr) ,_countRef(new int(1)) {} SharedPtr(const SharedPtr<T, D>& sp) :_ptr(sp._ptr) ,_countRef(sp._countRef) { ++(*_countRef); } SharedPtr<T, D>& operator=(const SharedPtr<T, D>& sp) { if(_ptr != sp._ptr) { Release(); _ptr = sp._ptr; use_count = sp.use_count; ++(*use_count); } return *this; } inline void Release() { if (--(*_countRef) == 0) { cout<<_ptr<<endl; //delete _ptr; _del(_ptr); delete _countRef; } } ~SharedPtr() { Release(); } //operator*() //operator->() int UseCount() { return *_countRef; }protected: T* _ptr; // int* _countRef; // 引用计数 D _del; // 定制的仿函数删除器};
但是shared_ptr指向一个双链表节点的时候会出现循环引用,也就是这个节点的引用计数是循环的
每个节点的引用计数永远是2,产生错误。
为了解决问题 boost库里引入weak_ptr指针解决。包含头文件
- smart_pointer
- 智能指针(smart_pointer)
- IntellJ IDEA常用快捷键大全
- MySQL配置单独放到一个文件中
- hihoCoder1040 : 矩形判断
- JDK/SDK
- swagger 注释
- smart_pointer
- 程序员面试金典——集合的子集______
- Go语言的结构嵌入问题
- 盘点在H5小游戏里常用的动效制作套路
- windows小技巧1——路径太长导致文件无法删除
- Xamarin XAML语言教程Xamarin.Forms中程序状态与进度(一)
- 关于CDN网络分发的工作机制
- 矢量图形引擎库VectorDraw Developer Framework 更新至v7.7011.0.4
- javascript根据元素自定义属性获取元素,操作元素