所谓智能指针指的是一种用起来像指针但又无需关心内存管理的一种机制。程序员
C/C++中指针极为常见,但普通指针最大的问题就在于须要程序员记住分配内存后要手动释放,不然就会有内存泄漏或者引用野指针的风险。微信
好比有这样一个简单的类:函数
class person { public: person() {} ~person(){ cout<<"delete person."<<endl; } void display(){ cout<<"This is person"<<endl; } };
若是在堆上分配该对象的话,那么在使用完后必须调用delete释放内存:this
person* p = new person(); ... delete p; //使用完后手动释放内存
那么有没有一种更好的机制来自动管理在堆上分配的对象呢?像下面这样:spa
smart_pointer p(new person()); p->display(); // 无需手动调用delete释放内存
答案是确定的。指针
指针本质上就是一个内存地址,所以普通指针根本就没法分辨何时该指针指向的内存使用完毕,code
普通指针须要更聪明一点。对象
什么状况下一块内存就能够释放掉了? 很简单,没人使用的时候就能够释放掉了。那么该怎么知道有没有人在使用一块内存?答案一样很简单,只须要记个数就能够了。ip
不知道你们去游乐园公园之类园区时有没有注意过,这些地方一般会显示园区里如今有多少人,有人进去这个数字就加1,有人出来这个数字就减一,何时管理员就能够关门了?固然是园区里没人的时候。内存
智能指针本质上就是园区里显示人数的指示牌,只不过在这里不叫人数,而是叫引用计数,Reference counting。
普通指针自己并不能告诉咱们是否指向的内存还有没有用,所以须要额外信息,这里的额外信息就是引用计数,将引用计数和智能指针组合在一块儿就是智能指针:
template<typename T> class smart_pointer { T* data; // 智能指针指向的内存 int count = 0; // 引用计数 };
建立智能指针时若是传入的是内存地址,那么咱们须要将引用计数设置为1,由于这是智能指针首次指向某个内存地址,智能指针构造函数以下:
smart_pointer(T* per){ data = per; count = 1; }
固然智能指针的构造函数也能够传入另外一个智能指针,这时咱们必须在原有引用计数的基础上加一,由于此时多了一个对该内存的引用,智能指针拷贝构造以下:
smart_pointer(const smart_pointer<T>& p){ data = p.data; count=p.count; ++count; }
当智能指针使用完毕被析构时就比如有人离开园区,这时必须判断引用计数是否为0,若是为0那么咱们应该关闭园区:
~smart_pointer(){ if ((--count) == 0) // 没有人在园区了 delete data; }
固然,智能指针首先用起来必须和普通指针同样,所以咱们须要重载指针的引用与解引用:
T& operator*(){ return *data; } T* operator->(){ return data; }
最后,不要忘了指针能够被赋值,所以智能指针也应该支持赋值,这样咱们须要重载赋值运算符。因为指针被赋值后会指向新的内存,所以在智能指针指向新的内存前必须离开当前所在的园区:
smart_pointer<T> operator=(const smart_pointer<T>& p){ if(this == &p) return *this; // 是本身人 if ((--count) == 0) delete data; // 没有人在这个园区了 data = p.data; // count = p.count; // 进到新园区 ++count; // return *this; }
简单的使用一下刚刚发明的新指针 :)
void test_smartpointer(){ smart_pointer<person> p(new person("tom",30)); p->display(); smart_pointer<person> q = p; q->display(); smart_pointer<person> m(q); m->display(); }
一切工做正常。
但愿这篇简短的介绍能对你们理解智能指针有所帮助。固然,在真实项目中你们要使用C++标准定义的智能指针。
若是你喜欢这篇文章,欢迎关注微信公共帐号码农的荒岛求生获取更多相关内容。
计算机内功决定程序员职业生涯高度