技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 算法 --> cpp智能指针的简单实现

cpp智能指针的简单实现

浏览:2925次  出处信息

   pointer

   因为c++没有拉圾回收的机制,所以,c++程序经常出现各种内存泄漏,一般而言,指针的new和delete需要对应,不然就会出现很严重的问题。而智能指针就是帮助我们自动管理指针的一种方式,比较常用的就是利用引用计数的方式,实现,当变量出了作用域时自动删除,当还有其他变量持有指针时不会删除。

   智能指针有很多实现方式,stl和boost库里都有实现,为了,便于理解和应用,我们来看看如何自己实现一个简单的智能指针。我这里要说的实现方式,是通过一个辅助类,来记录引用计数来操作的。

   看了很多其他人写的关于智能指针的内容,都没有说明为什么要这么实现。要自己想清楚智能指针的实现,首要的就是要去理解c++的内存分配和管理的方式。

   像很多c++书中说的那样,c++的内存存储主要分为两部分,栈和堆。我们声明的各种非指针的类型,比如int,char,类等都是分配在栈中的,这里面的内存是自动管理,我们不需要操心的,所以当这些内容超出了它的作用域时就会被自动回收。

  • int* test1() {
  •    int x = 2;
  •    int *xp = &x;
  •    return xp;
  • }
  • void test2() {
  •    int *xp = test1();
  •    *xp = 3;
  • }

   像这样的调用是有问题的,xp的指针是指向x的内存地址的,当出了test1函数的作用域时x会被回收,再对这个地址操作就是有问题了。

   在c++中,我们通过new和malloc方式得到的内存是分配在堆上的,这些内存如果我们不回收会一直存在那里,即使出了作用域也有,也就是如果new出的东西自己不去delete,系统也不会帮你回收,这样就会造成内存泄漏。所以通过new得到的内存我们需要自己去delete,同样malloc得到的内存需要自己去free。

   于是结合这两种内存分配机制,我们就可以构造我们自己的智能指针了。我们需要使用指针时我们只需要用自己构造的指针类,用类来生成实例,这种instance是分配在栈上的,出了作用域就会被自动回收。而指针类有一个成员变量,它是指向智能指针实例的指针,也就是我们的辅助类,辅助类中记录了引用次数,看代码。

  • #include <cstdio>
  • #include <cstring>
  • class SmartPtr {
  •    public:
  •        int count;
  •        int *p;
  •        SmartPtr(): count(1), p(new int()) {}
  •        ~SmartPtr() {
  •            printf("%d smart_ptr deleted\n", *p);
  •            delete p;
  •        }
  • };
  • class Ptr {
  •    public:
  •        SmartPtr *sp;
  •        Ptr(): sp(new SmartPtr()) {}
  •        Ptr(const Ptr& other): sp(other.sp) {
  •            sp->count++;
  •        }
  •        Ptr& operator=(const Ptr& other) {
  •            sp = other.sp;
  •            sp->count++;
  •            return *this;
  •        }
  •        ~Ptr() {
  •            if (--sp->count == 0)
  •                delete sp;
  •        }
  • };
  • Ptr test() {
  •    Ptr p1;
  •    *(p1.sp->p) = 8;
  •    Ptr p2;
  •    *(p2.sp->p) = 16;
  •    return p1;
  • }
  • int main() {
  •    Ptr p;
  •    *(p.sp->p) = 4;
  •    Ptr p2 = p;
  •    printf("%d %d\n", *(p2.sp->p), p.sp->count);
  •    Ptr p3 = test();
  •    printf("%d\n", *(p3.sp->p));
  •    return 0;
  • }

   需要指针时都是通过类生成实例的方式来使用,而不是直接只用指针,指针类Ptr中有指向辅助类的指针,这样Ptr的实例超出作用域时会被自动回收,而记录数据的辅助类因为是new出来的,所以会一直存在在那里,当有复制等行为时,引用计数相应增加,而Ptr被回收时引用计数也相应的减少,当引用计数为0的时候,就可以delete掉辅助类了。

   代码和程序还是很清晰的,可以自己运行看看,感觉智能指针也是一种帮助理解c++内存管理的方式,当对一切原理都清楚的时候,注意不同的内存分配,写程序也会变得很轻松了。


建议继续学习:

  1. Linus:利用二级指针删除单向链表    (阅读:11135)
  2. C语言结构体里的成员数组和指针    (阅读:4589)
  3. 通过引用计数解决野指针的问题(C&C++)    (阅读:3354)
  4. C 语言中统一的函数指针    (阅读:2969)
  5. 重构发现:指针操作问题    (阅读:2276)
  6. 空指针的解引用    (阅读:2155)
  7. 关于类成员函数指针的正确写法    (阅读:1919)
  8. 一起空指针引发的程序问题的排查过程    (阅读:1895)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1