菜鸟笔记
提升您的技术认知

c 智能指针详解-ag真人游戏

c/c 常为人诟病的一点是没有像java一样的内存回收机制(gc),因而对内存的管理和访问十分容易出错。c语言作为一种相对低级和轻量级的语言,内存的使用大部分都需要程序员自己操作,如创建数组和链表等,内存访问越界、悬浮指针和野指针等问题屡见不鲜。不过根据个人感觉,相对来说,c语言更底层,没有c 的抽象能力强,只要细心,这些问题阻止不了c的流行,而c 就复杂多了,完全靠程序员来做这些事很容易犯错,因此c 提供了各种各样的容器如vector、map和智能指针,大大减轻了程序员们对内存管理和使用的负担。

智能指针其实就是类对象,程序员将指针交给这些对象,指针被封装起来,内存的管理交由这些对象负责,我们通过其提供的接口使用指针。

template
class auto_ptr
{
private:
    t*ap;
public:
    //constructor & destructor-----------------------------------(1)
    explicit auto_ptr(t*ptr=0)throw():ap(ptr)
    {
    }
    ~auto_ptr()throw()
    {
        delete ap;
    }
    //copy & assignment--------------------------------------------(2)
    auto_ptr(auto_ptr& rhs)throw():ap(rhs.release())
    {
    }
    template
    auto_ptr(auto_ptr&rhs)throw():ap(rhs.release())
    {
    }
    auto_ptr& operator=(auto_ptr&rhs)throw()
    {
        reset(rhs.release());
        return*this;
    }
    template
    auto_ptr& operator=(auto_ptr&rhs)throw()
    {
        reset(rhs.release());
        return*this;
    }
    //dereference----------------------------------------------------(3)
    t& operator*()const throw()
    {
        return*ap;
    }
    t* operator->()const throw()
    {
        returnap;
    }
    //helper functions------------------------------------------------(4)
    //value access
    t* get()const throw()
    {
        returnap;
    }
    //release owner ship
    t* release()throw()
    {
        t*tmp(ap);
        ap=0;
        return tmp;
    }
    //reset value
    void reset(t*ptr=0)throw()
    {
        if(ap!=ptr)
        {
            deleteap;
            ap=ptr;
        }
    }
    //special conversions-----------------------------------------------(5)
    template
    struct auto_ptr_ref
    {
        y*yp;
        auto_ptr_ref(y*rhs):yp(rhs){}
    };
    auto_ptr(auto_ptr_refrhs)throw():ap(rhs.yp)
    {
    }
    auto_ptr& operator=(auto_ptr_refrhs)throw()
    {
        reset(rhs.yp);
        return*this;
    }
    template
    operator auto_ptr_ref()throw()
    {
        returnauto_ptr_ref(release());
    }
    template
    operator auto_ptr()throw()
    {
        returnauto_ptr(release());
    }
};

这是auto_ptr的类源码,可以看到其提供的接口。智能指针的构造函数一般声明成explicit,即不允许隐式转换,需要显式调用构造函数生成智能指针对象。既然是指针,就必须可以实现指针的功能,并且用起来要尽量像指针,因此智能指针都重载了operator *()和operator ->(),但是不支持指针的数学运算。
智能指针的种类不少,有auto_ptr、scoped_ptr、unique_ptr、shared_ptr、weak_ptr、shared_array等。auto_ptr是c 98中的,比较粗糙,使用比较简单,也不安全,因为不允许多个auto_ptr拥有同一个指针,在c 11中已被废弃,不建议使用,应该使用unique_ptr。

scoped_ptr顾名思义,指针的有效性和作用域相关。当scoped_ptr对象离开作用域时,其析构函数被调用,析构掉其指向的对象,避免内存泄露。

shared_ptr是功能最强大,使用最普遍的智能指针了,无论怎么重视都不为过。shared_ptr才是真正实用的类似gc的智能指针,其他的智能指针大多都比较简单,不支持对象的共享,使用范围比较窄,只适用于一些简单的情况。shared_ptr顾名思义,多个shared_ptr对象可以指向同一个对象,但并不会拷贝对象,而只拷贝其指针。这时,delete对象就不能简单地直接析构对象了,否则会造成其他指针失效,成为野指针,而需要对对象进行引用计数,每当有一个shared_ptr指向这个对象,其引用计数加一;每当delete一次,其引用计数减一,当引用计数减为0时,表明没有指针指向这个对象了,此时这个对象才会真正被删除。

weak_ptr更像是shared_ptr的辅助类,weak_ptr不增加对象的引用计数,可以用来观察对象的引用情况,并在需要的时候通过weak_ptr构造shared_ptr.

想要详细地介绍智能指针应该对每种指针的原理、实现进行说明,并写些示例代码示范其用法,每种智能指针都需要专门写文章来分析,可惜一来我自己的水平也不高,二来时间和精力有限,所以只能粗浅地写一写,大概介绍一下智能指针的概念,待以后再完善补充吧。因为水平有限必然会有很多疏漏及错误,欢迎批评指正

网站地图