zoukankan      html  css  js  c++  java
  • [C++]智能指针的实现与使用

    智能指针

    智能指针是当我们在使用对象时,有时会把对象的内存分配在堆上忘记释放,导致内存泄露,并且当多个指针共享同一个对象的内存时,容易出现重复释放内存,导致错误。
    

    我们针对所需要共享的对象,手动完成一个智能指针类来代替该类别的指针,自动帮我们释放内存,共享内存。以一个共享Object类的对象数据来说明两个版本的共享指针的实现。

    class Object {
    public:
        int a;
        int b;
    };
    

    基本版本的智能指针

    以下为一个最简单版本的智能指针,利用自动调用析构函数来调用delete函数,释放内存。但该智能指针不能实现引用计数来共享内存,只能帮我们管理单个对象内存的自动释放。

    /* version1 of smartpointer*/
    class SmartPointer {
    public:
        SmartPointer(Object* p) {
            cout<<"get pointer"<<endl;
            ptr = p;
        }
        ~SmartPointer() {
            cout<<"free memory"<<endl;
            delete ptr;
        }
    private:
        Object *ptr;
    };
    
    void process(SmartPointer &p) {
        //void process(SmartPointer &p) {
        cout<<"processing..."<<endl;
    }
    

    使用方法

    int main() {
    	SmartPointer P(new Object);
    	process(p);
    	return 0;
    }
    

    增加版本的智能指针

    当多个智能指针指向同一段内存时, 我们需要加强我们的智能指针的功能:

    • 引用计数:记录当前有多少个指针指向共享对象
    • 当引用计数为0时,释放共享对象内存
    • 构造函数与赋值构造函数的实现
    • 箭头运算符->与解引用运算符*的重载

    为了更加智能的管理引用计数与共享内存,我们实现Counter类帮我们的智能指针管理。指向同一个共享对象的智能指针共享同一个Counter对象。关系如下:

    class Counter {
        // SmartPointerPro设置为友元,否则smartpointerpro内部不能访问私有成员cnt与ptr
        friend class SmartPointerPro;
    public:
        Counter() {
            ptr = NULL;
            cnt = 0;
        }
        Counter(Object *p) {
            ptr = p;
            cnt = 1;
        }
        ~Counter() {
            delete ptr;
        }
    private:
        Object *ptr;
        int cnt;
    };
    

    下面是增加版本智能指针的实现

    /* version2 of smartpointer: need a counter class to count shared times*/
    class SmartPointerPro {
    public:
        // 当对像传入时,需要初始化一个counter来记录该对象共享次数
        SmartPointerPro(Object *p) {
            ptr_counter = new Counter(p);
        }
        // 用一个smartpointer来初始化另一个smartpointer,counter中共享次数+1
        SmartPointerPro(const SmartPointerPro &sp) {
            ptr_counter = sp.ptr_counter;
            ++ptr_counter->cnt;
        }
        // 相互赋值时:等号左边的对象被覆盖,cnt减一,等号右边对象共享次数加一
        SmartPointerPro& operator=(const SmartPointerPro &sp) {
            ++sp.ptr_counter->cnt;
            --ptr_counter->cnt;
            if (ptr_counter->cnt == 0) {
                delete ptr_counter;
            }
            ptr_counter = sp.ptr_counter;
        }
        ~SmartPointerPro() {
            --ptr_counter->cnt;
            if (ptr_counter->cnt == 0) {
                delete ptr_counter;
            }
        }
        Object *operator->() {
            return ptr_counter->ptr;
        }
        // 返回值为引用型,说明解引用后直接可以调用其它操作
        Object &operator*() {
            return *(ptr_counter->ptr);
        }
    private:
        Counter *ptr_counter;
    };
    

    增加版智能指针使用方法

    int main() {
        SmartPointerPro p(new Object());
        p->a = 10;
        p->b = 20;
        int a_val = (*p).a;
        int b_val = (*p).b;
        cout<<"p->a, p->b, a_val, b_val: "
            <<p->a<<" "<<p->b<<" "<<a_val<<" "<<b_val<<" "<<endl;
        SmartPointerPro q(p);
        cout<<"q->a, q->b: "<<q->a<<" "<<q->b<<endl;
        return 0;
    }
    

    系统实现的智能指针

    以上增加版本的智能指针看起来很好用,但是每次使用都需要先定义SmartPointerPro与Counter类,那么有没有系统库可以调用呢?答案是肯定的,但是需要我们先安装boost库。安装之后,

    #include <boost::shared_ptr>
    

    就可以使用系统实现的智能指针了,系统版本实现原理与我们增加版本智能指针原理基本相同。具体使用方法参考

    参考

    chapter-nine

  • 相关阅读:
    暴力+前缀和——cf1335E
    【经典】区间dp——cf1336E
    简单几何+并查集 —— 2015NAQ K
    spring mvc 文件上传 和 异常页面处理
    ajax 入门
    Codeforces Round #558 (Div. 2)
    [SDOI2019]热闹又尴尬的聚会(图论+set+构造)
    [SDOI2019]移动金币(博弈论+阶梯Nim+按位DP)
    [ZJOI2019]浙江省选(半平面交)
    [ZJOI2019]开关(生成函数+背包DP)
  • 原文地址:https://www.cnblogs.com/fariver/p/7227590.html
Copyright © 2011-2022 走看看