学习笔记八:试图利用C++ Primer 13.5节内容分析shared_ptr指针(共享智能指针)

C++ Primer 13.5节讲述的是管理类内指针成员的内容。作者分析了采用若采用普通的指针会导致不同对象的指针成员纠缠在一起。这时,作者通过引入一种“使用计数”的方式,介绍了“智能指针”的概念。(当然这里作者只是简单地演示了智能指针的“计数”思想,不过,从这我们也可以一窥共享智能指针shared_ptr的原理)
下面我将书中的例子贴出,并对其进行简单分析。

#include <iostream>

using namespace std;

// private class for use by HasPtr only
class U_Ptr {
    friend class HasPtr;
    int *ip;
    size_t use;
    U_Ptr(int *p): ip(p), use(1) { }
    ~U_Ptr() 
    { 
        delete ip; 
    }
};

/* smart pointer class: takes ownership of the dynamically allocated
 *          object to which it is bound
 * User code must dynamically allocate an object to initialize a HasPtr
 * and must not delete that object; the HasPtr class will delete it
 */
class HasPtr {
public:
    // HasPtr owns the pointer; pmust have been dynamically allocated
    HasPtr(int *p, int i): ptr(new U_Ptr(p)), val(i) 
    { }

    // copy members and increment the use count
    HasPtr(const HasPtr &orig):
    ptr(orig.ptr), val(orig.val) 
    { 
        ++ptr->use; 
    }
    HasPtr& operator=(const HasPtr&);

    // if use count goes to zero, delete the U_Ptr object
    ~HasPtr() 
    { 
        if (--ptr->use == 0) 
            delete ptr;
    }

    int *get_ptr() const { return ptr->ip; }
    int get_int() const { return val; }

    // change the appropriate data member
    void set_ptr(int *p) { ptr->ip = p; }
    void set_int(int i) { val = i; }

    // return or change the value pointed to, so ok for const objects
    // Note: *ptr->ip is equivalent to *(ptr->ip)
    int get_ptr_val() const { return *ptr->ip; }
    void set_ptr_val(int i) { *ptr->ip = i; }

private:
    U_Ptr *ptr;        // points to use-counted U_Ptr class
    int val;
};

HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
    ++rhs.ptr->use;     // increment use count on rhs first
    if (--ptr->use == 0)
        delete ptr;    // if use count goes to 0 on this object, delete it
    ptr = rhs.ptr;      // copy the U_Ptr object
    val = rhs.val;      // copy the int member
    return *this;
}


int main()
{
    /*int obj = 0;
    HasPtr p1(&obj, 42);*/
    int *p_int = new int(0);
    HasPtr p1(p_int, 42);
    HasPtr p2(p1);
    int *p_int1 = new int(10);
    HasPtr p3(p_int1,43);
    p2 = p3;

    return 0;
}

首先这段代码能够正确执行。实现功能为:初始化类p1,然后利用p1对p2进行复制初始化;之后初始化类p3,并将p3赋值给p2。
智能指针优点:由于采用“使用计数”的思想,所以当某个类的内存被释放,只要U_Ptr类对象的数据成员use!=0,指针共享对象内存就不会被释放,很好地解决了因为内存释放缘故造成的程序崩溃。
原文可能出现了错误:
在原文中对p1类的初始化是这样的:

int obj = 0;
HasPtr p1(&obj, 42);

但是我认为这是错误的,运行示例也证实了我的观点(编译不会出错,但执行时出现致命错误)。
这里,我认为出现这种状况的原因是,我们在定义智能指针时,析构函数中使用了delete p; 命令,这样注定了p只能指向堆内存(栈内存不能执行delete命令),且之前肯定要使用new命令分配一块内存。但是上述代码段却将存在于栈内存中的obj的地址赋给ptr,所以在执行U_Ptr的析构命令时,出现错误。其正确写法应该为:

int *p_int = new int(0);
HasPtr p1(p_int, 42);

从这些代码里我们可以看到boost库shared_ptr的影子,它之所以不需要用户delete内存,是因为在类内的析构函数中它已经帮你做啦。不过这也是shared_ptr在初始化是,必须要用new或同类对象初始化的原因(否则new和delete不能配对)。另外,boost使用了保护机制,它不允许share_ptr和普通指针之间的相互复制和赋值,这样可以避免普通指针指向栈内存时,再将其传给shared_ptr后,引起的致命错误(就如上述我们分析的那样)。(当然,关于boost库中的shared_ptr不能与普通指针相互转化是我个人理解,不确保一定正确

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值