如何实现一个简单的智能指针

野性酷女 2021-11-09 03:34 433阅读 0赞

所谓智能指针指的是一种用起来像指针但又无需关心内存管理的一种机制。

普通指针的问题

C/C++中指针极为常见,但普通指针最大的问题就在于需要程序员记住分配内存后要手动释放,否则就会有内存泄漏或者引用野指针的风险。

比如有这样一个简单的类:

  1. class person {
  2. public:
  3. person() {}
  4. ~person(){ cout<<"delete person."<<endl; }
  5. void display(){
  6. cout<<"This is person"<<endl;
  7. }
  8. };

如果在堆上分配该对象的话,那么在使用完后必须调用delete释放内存:

  1. person* p = new person();
  2. ...
  3. delete p; //使用完后手动释放内存

那么有没有一种更好的机制来自动管理在堆上分配的对象呢?像下面这样:

  1. smart_pointer p(new person());
  2. p->display();
  3. // 无需手动调用delete释放内存

答案是肯定的。

让指针更智能

指针本质上就是一个内存地址,因此普通指针根本就无法分辨什么时候该指针指向的内存使用完毕

普通指针需要更聪明一点。

什么情况下一块内存就可以释放掉了? 很简单,没人使用的时候就可以释放掉了。那么该怎么知道有没有人在使用一块内存?答案同样很简单,只需要记个数就可以了。

不知道大家去游乐园公园之类园区时有没有注意过,这些地方通常会显示园区里现在有多少人,有人进去这个数字就加1,有人出来这个数字就减一,什么时候管理员就可以关门了?当然是园区里没人的时候。

智能指针本质上就是园区里显示人数的指示牌,只不过在这里不叫人数,而是叫引用计数,Reference counting。

带有引用计数的指针:智能指针

普通指针本身并不能告诉我们是否指向的内存还有没有用,因此需要额外信息,这里的额外信息就是引用计数,将引用计数和智能指针组合在一起就是智能指针

  1. template<typename T>
  2. class smart_pointer
  3. {
  4. T* data; // 智能指针指向的内存
  5. int count = 0; // 引用计数
  6. };

创建智能指针时如果传入的是内存地址,那么我们需要将引用计数设置为1,因为这是智能指针首次指向某个内存地址,智能指针构造函数如下:

  1. smart_pointer(T* per){
  2. data = per;
  3. count = 1;
  4. }

当然智能指针的构造函数也可以传入另一个智能指针,这时我们必须在原有引用计数的基础上加一,因为此时多了一个对该内存的引用,智能指针拷贝构造如下:

  1. smart_pointer(const smart_pointer<T>& p){
  2. data = p.data;
  3. count=p.count;
  4. ++count;
  5. }

当智能指针使用完毕被析构时就好比有人离开园区,这时必须判断引用计数是否为0,如果为0那么我们应该关闭园区:

  1. ~smart_pointer(){
  2. if ((--count) == 0) // 没有人在园区了
  3. delete data;
  4. }

当然,智能指针首先用起来必须和普通指针一样,因此我们需要重载指针的引用与解引用:

  1. T& operator*(){
  2. return *data;
  3. }
  4. T* operator->(){
  5. return data;
  6. }

最后,不要忘了指针可以被赋值,因此智能指针也应该支持赋值,这样我们需要重载赋值运算符。由于指针被赋值后会指向新的内存,因此在智能指针指向新的内存前必须离开当前所在的园区:

  1. smart_pointer<T> operator=(const smart_pointer<T>& p){
  2. if(this == &p)
  3. return *this; // 是自己人
  4. if ((--count) == 0)
  5. delete data; // 没有人在这个园区了
  6. data = p.data; //
  7. count = p.count; // 进到新园区
  8. ++count; //
  9. return *this;
  10. }
应用

简单的使用一下刚刚发明的新指针 ?

  1. void test_smartpointer(){
  2. smart_pointer<person> p(new person("tom",30));
  3. p->display();
  4. smart_pointer<person> q = p;
  5. q->display();
  6. smart_pointer<person> m(q);
  7. m->display();
  8. }

一切工作正常。

总结

希望这篇简短的介绍能对大家理解智能指针有所帮助。当然,在真实项目中大家要使用C++标准定义的智能指针。

如果你喜欢这篇文章,欢迎关注微信公共账号码农的荒岛求生获取更多相关内容。

在这里插入图片描述

计算机内功决定程序员职业生涯高度

发表评论

表情:
评论列表 (有 0 条评论,433人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++智能指针简单剖析

    智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针。智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放。 1. 智能指针背后的设

    相关 基于C++实现一个简单智能指针

    在C、C++类的语言当中对指针的使用是十分常见和重要的,但是使用指针也很容易导致内存泄漏、不安全的情况发生,本文就针对这种情况来实现一个简单的智能指针类,通过这个类实现对指针操

    相关 C++-智能指针——简单实现分析

    > 一:为什么要有智能指针 在我们动态开辟内存时,每次new完就一定会有配套的delete来完成释放操作。可是这时候问题就来了,有时候程序未必会执行到我们释放的那一步,