C++智能指针(一):智能指针的简单介绍

RAII

定义

RAII(Resource Acquisition Is Initialization),也称为“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的惯用法。C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。简单的说,RAII 的做法是使用一个对象,在其构造时获取资源,在对象生命期控制对资源的访问使之始终保持有效,最后在对象析构的时候释放资源。

分类

根据RAII 对资源的所有权可分为常性类型和变性类型,代表者分别是boost:shared_ptr<>和std::auto_ptr<>;从所管资源的初始化位置上可分为外部初始化类型和内部初始化类型。

常性类型是指获取资源的地点是构造函数,释放点是析构函数,并且在这两点之间的一段时间里,任何对该RAII类型实例的操纵都不应该从它手里夺走资源的所有权。

变性类型是指可以中途被设置为接管另一个资源,或者干脆被置为不拥有任何资源。外部初始化类型是指资源在外部被创建,并被传给RAII实例的构造函数,后者进而接管了其所有权。boost:shared_ptr<>和std::auto_ptr<>都是此类型。与之相对的是内部初始化类型。


智能指针

为什么使用智能指针

1.我们首先看一段小程序:

int main()
{
    int *ptr = new int(0);
    return 0;
 }

上面的程序我们可以看出什么问题??我们申请的内存最后忘记了释放,从而导致了内存泄漏。

2.我们再看一个程序:

int main()
{
    int *ptr = new int(0);
    delete ptr;
    return 0;
 }

这次我们释放了已经申请的空间,是不是已经没问题了??我们虽然释放了内存,却没有把ptr指针置空,这就可能使它指向其他内存,形成野指针,这会给程序带来很多隐患!!

我们上面两个问题,一直忽略了new空间失败的情景。如果内存申请不成功,new会抛出异常,而我们却什么都没有做!所以对这程序我们还得继续改进(也可用try…catch…):

int main()
{
     int *ptr = new(nothrow) int(0);
    if(!ptr)
    {
       cout << "new fails."
        return 0;
     }
     delete ptr;
     ptr = NULL;
     return 0;
 }

3.我们再看最后一段程序:

int main()
{
    int *ptr = new(nothrow) int(0);
    if(!ptr)
    {
        cout << "new fails."
        return 0;
    }
    // 假定hasException函数原型是 bool hasException()
    if (hasException())
        throw exception();

    delete ptr;
    ptr = nullptr;
    return 0;
}

当我们的程序运行到“if(hasException())”处且“hasException()”为真,那程序将会抛出一个异常,最终导致程序终止,而已申请的内存并没有释放掉。
当然,我们可以在“hasException()”为真时释放内存:

// 假定hasException函数原型是 bool hasException()
if (hasException())
{
     delete ptr;
     ptr = nullptr;
     throw exception();
}

但是,我们并不总会想到这么做。而且,这样子做也显得麻烦,不够人性化。

如果,我们使用智能指针,上边的问题我们都不用再考虑,因为它都已经帮我们考虑到了。

小结:

我们使用智能指针的原因至少有以下三点:

  1. 智能指针能够帮助我们处理资源泄露问题;
  2. 它也能够帮我们处理空悬指针的问题;
  3. 它还能够帮我们处理比较隐晦的由异常造成的资源泄露。

智能指针的发展

智能指针的发展可分为三个部分:

  1. auto_ptr 管理权的转移–带有缺陷的设计–C++98/03
  2. scoped_ptr(boost) unique_ptr(c++11) 防拷贝 –简单粗暴的设计 –功能不全
  3. shared_ptr(boost/c++11) 引用计数 –功能强大(支持拷贝,支持定制删除器) 缺陷–循环引用(可采用weak_ptr配合解决)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值