自己理解的智能指针

看安卓内核,第一章就碰到智能指针了。

看了网上的一些文章,自己实践了一下。

自己的体会:

普通指针直接为某个具体类型分配空间,对该空间的管理直接由指针来操作。T* p=new  T(t);

智能指针相当于对该空间进行封装。智能指针实际是一个类,shared_ptr<T> sp(new T(t));

类里面包含一个成员,uptr(T* t,size_t use)。

uptr除了保存着普通指针指向的具体空间外,uptr还有个成员,引用计数。

因此,普通指针p对其指向空间的操作,在智能指针中表现为sp对其成员uptr的操作。

普通指针存在危险的原因比如忘了delete或者多次delete

1.智能指针利用(RAII)解决忘了delete

2.由于智能指针是一个类,其析构函数相当于对其成员utp执行析构,~uptr();

uptr执行析构时,不会直接调用系统的delete,而是判断use==0,才delete.这里也体现了面向对象的封装。

因此解决了多次delete的问题

网上的文章中,发现有一篇文章貌似被推荐挺多次的,

http://blog.csdn.net/hackbuteer1/article/details/7561235

但是我觉得他写错了。哈哈

正确的应该是下面这样写(class Hasptr,Uptr是primer上面的,不会错,但是他在使用的时候用错了。相当于不是对类进行直接使用,而是把类转化为指针。这样子RAII是没办法产生作用的)

#include<iostream>
using namespace std;  

// 定义仅由HasPtr类使用的U_Ptr类,用于封装使用计数和相关指针
// 这个类的所有成员都是private,我们不希望普通用户使用U_Ptr类,所以它没有任何public成员
// 将HasPtr类设置为友元,使其成员可以访问U_Ptr的成员
class U_Ptr
{
    friend class HasPtr;
    int *ip;
    size_t use;
    U_Ptr(int *p) : ip(p) , use(1)
    {
        cout << "U_ptr constructor called !" << endl;
    }
    ~U_Ptr()
    {
        delete ip;
        cout << "U_ptr distructor called !" << endl;
    }
};  

class HasPtr
{
public:
    // 构造函数:p是指向已经动态创建的int对象指针
    HasPtr(int *p, int i) : ptr(new U_Ptr(p)) , val(i)
    {
        cout << "HasPtr constructor called ! " << "use = " << ptr->use << endl;
    }  

    // 复制构造函数:复制成员并将使用计数加1
    HasPtr(const HasPtr& orig) : ptr(orig.ptr) , val(orig.val)
    {
        ++ptr->use;
        cout << "HasPtr copy constructor called ! " << "use = " << ptr->use << endl;
    }  

    // 赋值操作符
    HasPtr& operator=(const HasPtr&);  

    // 析构函数:如果计数为0,则删除U_Ptr对象
    ~HasPtr()
    {
        cout << "HasPtr distructor called ! " << "use = " << ptr->use << endl;
        if (--ptr->use == 0)
            delete ptr;
    }  

    // 获取数据成员
    int *get_ptr() const
    {
        return ptr->ip;
    }
    int get_int() const
    {
        return val;
    }  

    // 修改数据成员
    void set_ptr(int *p) const
    {
        ptr->ip = p;
    }
    void set_int(int i)
    {
        val = i;
    }  

    // 返回或修改基础int对象
    int get_ptr_val() const
    {
        return *ptr->ip;
    }
    void set_ptr_val(int i)
    {
        *ptr->ip = i;
    }
private:
    U_Ptr *ptr;   //指向使用计数类U_Ptr
    int val;
};
HasPtr& HasPtr::operator = (const HasPtr &rhs)  //注意,这里赋值操作符在减少做操作数的使用计数之前使rhs的使用技术加1,从而防止自我赋值
{
    // 增加右操作数中的使用计数
    ++rhs.ptr->use;
    // 将左操作数对象的使用计数减1,若该对象的使用计数减至0,则删除该对象
    if (--ptr->use == 0)
        delete ptr;
    ptr = rhs.ptr;   // 复制U_Ptr指针
    val = rhs.val;   // 复制int成员
    return *this;
}
void func();
int main(void)
{  

	func();
    return 0;
}
void func(){
	int *pi = new int(42);
    HasPtr hpa(pi, 100);    // 构造函数
    HasPtr hpb =  HasPtr(hpa);     // 拷贝构造函数
   // HasPtr *hpc = new HasPtr(*hpb);     // 拷贝构造函数
    HasPtr hpd = hpa;     // 拷贝构造函数  

    cout << hpa.get_ptr_val() << " " << hpb.get_ptr_val() << endl;
   // hpc->set_ptr_val(10000);
   // cout << hpa.get_ptr_val() << " " << hpb->get_ptr_val() << endl;
    hpd.set_ptr_val(10);
    cout << hpa.get_ptr_val() << " " << hpb.get_ptr_val() << endl;
  //  delete hpa;
   // delete hpb;
  //  delete hpc;
    cout << hpd.get_ptr_val() << endl;  

}

而按照链接上那位仁兄的,把main代码放到func中,当退出func的作用域的时候,引用计数没有变为0。也就也就意味着那片空间没有释放。

//fresh

重新看了那位仁兄的,他后面手动调用了delete hasptr;。...怎么说呢,既然手动调用,干嘛还用智能指针?

而且那位仁兄delete的时候,忘了delete hpd;

典型的传统指针引发的问题。

他估计是为了展示智能指针的引用计数能够正确的递增。

但是智能指针的真正作用应该是为了防止内存泄露。

时间: 2024-10-16 15:11:35

自己理解的智能指针的相关文章

对智能指针的一些理解

c++本身不提供自动内存回收机制,所以每次我们有new一个对象或者数组,我们都是时时刻刻提醒自己要记得去delete new出来的对象,那样岂不是非常烦人?而且就算你记得在析构函数中delete new出来的对象,也同样会造成很多问题,比如一个class里面有个指针,初始化的时候new了一块内存,然后class 有个对象a,再通过class b=a复制一份a,这样其实两个对象分别有一个指针指向new的那块内存,当有一个对象生命周期结束的,析构函数释放了那块内存,然后另外一个对象生命周期结束再去释

智能指针的理解

1. shared_ptr是要程序管理的对象,这个对象管理了它引用的另一个对象 2. shared_ptr销毁的时候,把它引用的对象的引用数减一,这个是强引用 3. weak_ptr可以认为是普通指针,它不管理它引用的对象的内存 左边的小方块是智能指针对象,右边P对象拥有一个引用C的智能指针,C要能P销毁后才能销毁

C++ Primer笔记8_动态内存_智能指针

1.动态内存 C++中,动态内存管理是通过一对运算符完成的:new和delete.C语言中通过malloc与free函数来实现先动态内存的分配与释放.C++中new与delete的实现其实会调用malloc与free. new分配: 分配变量空间: int *a = new int; // 不初始化 int *b = new int(10); //初始化为10 string *str = new string(10, ); 分配数组空间: int *arr = new int[10];//分配的

C++智能指针剖析(下)boost::shared_ptr&amp;其他

1. boost::shared_ptr 前面我已经讲解了两个比较简单的智能指针,它们都有各自的优缺点.由于 boost::scoped_ptr 独享所有权,当我们真真需要复制智能指针时,需求便满足不了了,如此我们再引入一个智能指针,专门用于处理复制,参数传递的情况,这便是如下的boost::shared_ptr. boost::shared_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件#include<boost/smart_ptr.hpp> 便可以使

C++中智能指针的设计和使用

转载请标明出处,原文地址:http://blog.csdn.net/hackbuteer1/article/details/7561235      智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露.它的一种通用实现技术是 使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针.每次创建类的新对象时,初始化指针并将引用计数置为

【C++深入浅出】智能指针之auto_ptr学习

起:  C++98标准加入auto_ptr,即智能指针,C++11加入shared_ptr和weak_ptr两种智能指针,先从auto_ptr的定义学习一下auto_ptr的用法. template<class _Ty> class auto_ptr { // wrap an object pointer to ensure destruction public: //定义_Myt类型,作用域局限于类中,便于书写和理解 typedef auto_ptr<_Ty> _Myt; typ

智能指针(模拟实现AutoPtr、ScopedPtr、SharedPtr)

模拟实现AutoPtr.ScopedPtr.SharedPtr 智能指针实际上就是能够智能化的管理动态开辟空间的内存释放问题,C++中引入智能指针,很大一方面是当我们在动态开辟空间时,由于一些疏忽,或者说是对于一些代码,执行的顺序不是我们预期能够想到的,导致一些内存泄露的问题,使得程序健壮性不够,可维护性降低. 智能指针的基本特点: 1)智能指针管理的是一块内存的释放. 2)智能指针是一个类,有类似指针的功能. 下面主要是AutoPtr的理解: 当我们了解上面的知识后,模拟实现智能指针AutoP

c++智能指针以及循环引用问题(转)

解决循环引用: 在知道存在循环引用的条件下,使用boost::weak_ptr,即弱引用来代替循环引用中的某个强引用,从而打破循环引用的环. 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete,比如流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见,并造成内存泄露.如此c++引入 智能指针 . c++ 智能指针主要包括:unique_ptr,shared_ptr, weak_ptr, 这三种,其中auto

C++11智能指针

C成也指针,败也指针.确实,指针给程序员提供了很多便利和灵活性,但是不当的指针使用也会造成很多问题. Java和C#避免了指针(虽然C#中也能使用指针,但是估计很少有人这样做),其垃圾回收机制,给程序员减轻很多管理内存的负担. 为了带来指针更好的使用体验,C++中引入了智能指针的概念,其实质就是将指针的一些操作封装成类,程序员通过使用熟悉的指针运算符(-> 和 *)访问封装指针,该指针类通过运算符重载返回封装的原始指针. C++ 智能指针思路类似于C#等语言中创建对象的过程:创建对象后让系统负责