美文网首页
深入理解 智能指针类 : 管理 指针成员

深入理解 智能指针类 : 管理 指针成员

作者: my_passion | 来源:发表于2020-10-03 19:43 被阅读0次

1 带 pointer mem 的 简单 class

1. default copy ctor / assignment, 都 只 copy pointer, 不 copy target object

`(1) synthesized copy ctor`
int obj = 0;
// ctor
HasPtr hp1(&obj, 0);

//默认复制
HasPtr hp2(hp1);
image.png
(2) synthesized assigment operator
int obj1 = 0;
HasPtr hp1(&obj1, 1);

int obj2 = 2;
HasPtr hp2(&obj, 3);

// synthesized assigment
HasPtr hp2 = hp1;
image.png

2. share target obj + 悬垂指针:

多个 HasPtr obj ( 的 internal ptr ) share the same pointed object 时, 1 个 delete the target obj -> 另一个 无法感知 target obj 是否存在 -> 若已 被 delete -> 悬垂指针

=> 
`由 HasPtr 的 client 保证 target obj 存在`
=>
`无法避免 悬垂指针`
int* p = new int(1);
HasPtr hp(p, 2);
delete p;  
hp.set_ptr_val(0); 

=>

p 与 hp.ptr 指向同一 obj, 
若 用 p delete this obj -> hp.ptr 指向 invalid 内存
// 5. implement of SP
#include <iostream>

template <class T>
class HasPtr
{
private:
    T* pt;
    int val;

public:
    HasPtr(T* pt1, int i) : pt(pt1), val(i) { }

    ~HasPtr()
    {
        //若 hp1 hp2 的 pointer mem  指向同一 obj, 
        //hp1 hp2 两者 后消亡者 call this dtor 时, 指针悬挂
        delete pt;
    }

    // common function
    T* get_ptr() const { return pt; }
    int get_val() const { return val; }

    void set_ptr(T* p) { pt = p; }
    void set_val(int i) { val = i; }

    T get_ptr_val() const { return *pt; }
    void set_ptr_val(T t) { *pt = t; }
};

int main()
{
    int* p1 = new int(5);
    int* p2 = new int(10);

    HasPtr<int> hp1 = HasPtr<int>(p1, 1);
    HasPtr<int> hp2 = HasPtr<int>(p2, 2);

    hp2 = hp1;
}

2 智能指针 / Smart Pointer ( SP ) class

本节 所讲 只是 shared_ptr

internal ptr 所指 object shared + class avoid 悬垂指针

1. 引用计数 ( reference count / RC )

用1个 counter 跟踪 SP class 有几个 object share the same ptr ( to target object )

仅当 SP object 感知到自己 ( 的 internal ptr )
is the last ptr ( 靠 RC ) to target object 时, dtor 中才 delete internal ptr

=> 调 the pointed/target object 的 dtor 
-> 再 free memory of  pointer mem itself
`2. 限制`
target obj 

(1) 由 client dynamically allocate -> address 传给 class HasPtr

(2) 不能被 non-SP 的 external ptr delete

(3) delete by the last HasPtr obj's internal ptr: 由 SP 保证

3. `SP 实现`
(1) ctor
    1) init. internal ptr
    2) counter = 1
    
(2) copy ctor
    1) copy ptr
    2) ++counter
    
(3) assignment operator
    1) 左 --counter, 
       若减为 0 -> delete ptr  
    2) 右 ++counter

(4) dtor
    --counter
       若减为 0 -> delete ptr

4. RC 放哪 ?

(1) 不能放 SP object 中
reason: 无法保证 all SP obj 中, RC 值 都正确

// eg.
copy ctor: 
1) old obj's RC++
2) new obj's RC update 为 old obj's RC

=>

1 个 SP obj 2次 copy:
原 obj 与 第 2 copy 的 RC 都 = 3, 
但 第 1 copy 的 RC = 
=> error
image.png
template <class T>
class HasPtr
{
private:
    T* pt;
    int val;
    size_t RC;
};

int obj;
HasPtr<int> hp(&obj, 10);
HasPtr<int> hp1(hp);
HasPtr<int> hp2(hp);
`(2) reference count 一种正确放置 的 策略`

用 1 个 class U_Ptr 封装 RC 与 internal ptr

U_Ptr 所有成员 private
1) 阻止 ordinary client use
2) SP 设为 U_Ptr 的 friend, 以使 SP's mem 可 access U_Ptr's mem

image.png
#include <iostream>

// forward declaration
template <class T>
class SP;

template <class T>
class U_Ptr
{
    // 1) SP as friend
    friend class SP<T>;
private:
    // 2) ptr + RC
    T* pt;
    size_t RC;

    // 3) single para ctor: RC init 1
    U_Ptr(T* _pt) 
        : pt(_pt), RC(1) { }

    // 4) dtor
    // SP dtor: delete pU -> call U_Ptr dtor: delete pt without check
    ~U_Ptr() { delete pt; } 
};

template <class T>
class SP
{
private:
    // note: class template internal / external: 
    // <T> must exist / needn't after class name
    U_Ptr<T>* pU; 
    
    int val;

public:
    //(1) ctor: pt passed by SP's client
    SP(T* pt, int _val) :
        pU( new U_Ptr<T>(pt) ), val(_val) { }

    //(2) copy ctor: ++RC
    SP(const SP& hp) : 
        pU(hp.pU), val(hp.val)
    {
        ++pU->RC;
    }

    //(3) operator=
    SP& operator=(const SP& rhs);

    //(4) dtor
    ~SP()
    {
        if (--pU->RC == 0)
            delete pU;
    }
};

template <class T>
SP<T>& 
SP<T>::operator=(const SP<T>& rhs)
{
    // 1) right ++RC
    ++rhs.pU->RC;
    
    // 2) left --RC
    if (--pU->RC == 0)
        delete pU;
    
    // 3) pU 赋值
    pU = rhs.pU;
    
    val = rhs.val;
    
    // 4)
    return *this;
}

int main()
{
    int* p1 = new int(5);
    int* p2 = new int(10);

    SP<int> hp = SP<int>(p1, 1);
    SP<int> rhp = SP<int>(p2, 2);

    hp = rhp;
}
image.png

3 值型 class

ctor / copy ctor: 以 T 型 arg 为 初值 -> new -> 被 internal ptr 指向

pointer mem 所指 object unique / 独立管理

// eg1.
#include <iostream>

template <class T>
class HasPtr
{
private:
    T* pt;
    int val;
public:
    // ctor
    HasPtr(const T& _t, int i) : 
        pt( new T(_t) ), 
        val(i) 
    { }

    // copy ctor
    //1) no longer copy pointer
    //2) allocate a new object
    //3) initialize new obj's value 
    //   equal to the copied obj's value
    HasPtr(const HasPtr& rhs) : 
        pt( new T(*rhs.pt) ), 
        val(rhs.val) 
    { }

    HasPtr& operator=(const HasPtr& rhs);

    ~HasPtr()
    {
        delete pt;
    }
};

template <class T>
HasPtr<T>& 
HasPtr<T>::operator=(const HasPtr<T>& rhs)
{
    //1) operator= 不需要 allocate new obj

    //2) 左右 操作数 相同时, 赋值也安全
    // => `不用 check 自身赋值`
    *pt = *rhs.pt;
    val = rhs.val;

    return *this;
}

int main()
{
    int a = 5;
    int b = 10;

    // 先 new 再调用 ctor 时, ctor 改成和 普通类中 相同

    HasPtr<int> hp1 = HasPtr<int>(a, 1);
    HasPtr<int> hp2 = HasPtr<int>(b, 2);

    hp2 = hp1;
}
// eg2. equivalent to eg1
template <class T>
class HasPtr
{
    //...
public:
    // ctor
    HasPtr(T* pt1, int i) : 
        pt(pt1), val(i) { }
};

int main()
{
    int* p1 = new int(5);
    int* p2 = new int(10);

    HasPtr<int> hp1 = HasPtr<int>(p1, 1);
    HasPtr<int> hp2 = HasPtr<int>(p2, 2);

    hp2 = hp1;
}

相关文章

  • 深入理解 智能指针类 : 管理 指针成员

    1 带 pointer mem 的 简单 class 1. default copy ctor / assignm...

  • 第十六章 string类和标准模板库(2)智能指针模板类

    (二)智能指针模板类 智能指针是行为类似指针的类对象,但这种对象还有其他便于管理内存的功能。 1.使用智能指针 (...

  • 4.类和对象(构造深入)

    数据成员指针 定义:数据类型类名:: *指针名 = &类名::数据成员 解引用:对象名.* 指针名对象指针 ->*...

  • C++智能指针

    智能指针其实本质是一个模板类,一般使用是用的这个类的对象,而不是指针智能指针体现在内存释放问题,用智能指针管理ne...

  • C++——指向类成员(数据函数)的指针

    一、指向类数据成员的指针 二、指向类成员函数的指针 三、总结

  • 类成员指针

    指向类的数据成员的指针: 指向数据成员的指针格式如下: <类型说明符><类名>::*<指针名> 例如,设有如下一个...

  • C++ 引用计数技术及智能指针的简单实现

    1.智能指针是什么 简单来说,智能指针是一个类,它对普通指针进行封装,使智能指针类对象具有普通指针类型一样的操作。...

  • C++面试重点再梳理

    智能指针 请讲一下智能指针原理,并实现一个简单的智能指针 智能指针其实不是一个指针。它是一个用来帮助我们管理指针的...

  • C++智能指针

    引用计数技术及智能指针的简单实现 基础对象类 辅助类 智能指针类 使用测试 参考: C++ 引用计数技术及智能指针...

  • 1.2.09_C++ 指向类的指针

    C++ 类 & 对象 一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算...

网友评论

      本文标题:深入理解 智能指针类 : 管理 指针成员

      本文链接:https://www.haomeiwen.com/subject/ajinuktx.html