Boost源码学习---scoped_ptr.hpp

scoped_ptr是一个智能指针,包装了指向堆上内存的指针。它对指针所有权加以限制,不能转让指针所有权,一旦scoped_ptr获取了指针的管理权,便不再释放,无法再从其取回来,就像scope意思一样,指针智能在作用域使用,不能转让出去。一旦离开scoped_ptr的作用域,将调用它的析构函数,释放指针,不用手动释放。下面是它的源代码:

#ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED

//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
//  Copyright (c) 2001, 2002 Peter Dimov
//
//  Distributed under the Boost Software License, Version 1.0. (See
//  accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
//  http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
//

#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
#include <boost/detail/workaround.hpp>

#ifndef BOOST_NO_AUTO_PTR
# include <memory>          // for std::auto_ptr
#endif

namespace boost
{

// Debug hooks

#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)

void sp_scalar_constructor_hook(void * p);
void sp_scalar_destructor_hook(void * p);

#endif

//  scoped_ptr mimics a built-in pointer except that it guarantees deletion
//  of the object pointed to, either on destruction of the scoped_ptr or via
//  an explicit reset(). scoped_ptr is a simple solution for simple needs;
//  use shared_ptr or std::auto_ptr if your needs are more complex.

template<class T> class scoped_ptr // noncopyable
{
private:

    T * px;//原生态指针
		//将复制构造函数和赋值操作符声明为私有,不允许在类外使用,这样就限制了其所有权的转让
    scoped_ptr(scoped_ptr const &);
    scoped_ptr & operator=(scoped_ptr const &);

    typedef scoped_ptr<T> this_type;

		//重载为私有,不支持比较
    void operator==( scoped_ptr const& ) const;
    void operator!=( scoped_ptr const& ) const;

public:

    typedef T element_type;
		//显示构造函数,必须显示调用
    explicit scoped_ptr( T * p = 0 ): px( p ) // never throws
    {
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost::sp_scalar_constructor_hook( px );
#endif
    }

#ifndef BOOST_NO_AUTO_PTR

		//参数为auto_ptr时的构造函数
		//p.release()设auto_ptr为NULL,返回其内部指针
    explicit scoped_ptr( std::auto_ptr<T> p ) BOOST_NOEXCEPT : px( p.release() )
    {
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost::sp_scalar_constructor_hook( px );
#endif
    }

#endif
		//析构函数,析构对象,释放内存
    ~scoped_ptr() // never throws
    {
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost::sp_scalar_destructor_hook( px );
#endif
        boost::checked_delete( px );
    }

    void reset(T * p = 0) // never throws
    {
        BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
        //把p转换为scoped_prt,再调用swap交换
        this_type(p).swap(*this);
    }
		//重载解引用,返回指针指向的对象
    T & operator*() const // never throws
    {
        BOOST_ASSERT( px != 0 );
        return *px;
    }
		//重载->,返回指针
    T * operator->() const // never throws
    {
        BOOST_ASSERT( px != 0 );
        return px;
    }
		//返回指针
    T * get() const BOOST_NOEXCEPT
    {
        return px;
    }

// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
		//交换两个指针
    void swap(scoped_ptr & b) BOOST_NOEXCEPT
    {
        T * tmp = b.px;
        b.px = px;
        px = tmp;
    }
};

#if !defined( BOOST_NO_CXX11_NULLPTR )

template<class T> inline bool operator==( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
{
    return p.get() == 0;
}

template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_NOEXCEPT
{
    return p.get() == 0;
}

template<class T> inline bool operator!=( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
{
    return p.get() != 0;
}

template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_NOEXCEPT
{
    return p.get() != 0;
}

#endif

template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) BOOST_NOEXCEPT
{
    a.swap(b);
}

// get_pointer(p) is a generic way to say p.get()

template<class T> inline T * get_pointer(scoped_ptr<T> const & p) BOOST_NOEXCEPT
{
    return p.get();
}

} // namespace boost

#endif // #ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED

scoped_ptr与auto_ptr不同的是:auto_ptr可以转让使用权,在转让的时候,上一个指针失去使用权。而scoped_ptr不允许转让使用权。

scoped_ptr和auto_ptr都不能放在容器,auto_ptr是因为它只允许一个auto_prt使用指针,而scoped_ptr是因为不允许转让使用权,不支持拷贝和复制,不符合容器对元素的要求。

时间: 2024-10-14 12:11:08

Boost源码学习---scoped_ptr.hpp的相关文章

Boost源码学习---shared_ptr.hpp

最近在看Boost库源码,Boost库功能强大,但是其源代码太多,一一细读太过于耗费时间,毕竟还有其他东西要学习,所以决定对感兴趣的章节略读一下,记录一下其设计思想和难以理解的地方. shared_ptr是Boost里面最有价值的的智能指针.它封装了一个原生态指针和一个引用计数器,这个引用计数器是一个类shared_count.shared_ptr支持比较运算,重载了operator<,因此其可以用于set和map. 在转换shared_ptr指针时,用***_pointer_cast定义的函数

Boost源码学习---weak_ptr.hpp

weak_ptr是辅助shared_ptr的智能指针.就像它的名字一样,是个"弱"指针:仅有几个接口,仅能完成很少工作.它可以从一个shared_ptr或weak_ptr对象构造,获取对资源的观测权,它是没有共享资源的,所以它的对象的创建不会引起指针引用计数的增加,它的对象的析构也不会引起计数器的减少. 它没有重载*和->,不能使用指针,主要的几个接口如下: long use_count() const//返回计数器数值 bool expired() const//判断指针是否失

Boost源码学习---

scoped_array功能类似scoped_ptr,scoped_array管理的是new[]开辟的数组,其析构函数调用的是delete[]释放数组. 它没有重载解引用*和箭头操作符->,因为它不是普通指针,而是一个数组.它重载了[],可以像使用数组下标那样访问数组. #ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED #define BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED // (C) Copyrig

FireMonkey 源码学习(5)

(5)UpdateCharRec 该函数的源码分析如下: procedure TTextLayoutNG.UpdateCharRec(const ACanvas: TCanvas; NeedBitmap: Boolean; var NewRec: PCharRec; HasItem: Boolean; const CharDic: TCharDic; const AFont: TFont; const Ch: UCS4Char; const NeedPath: Boolean = False);

jquery源码学习

jQuery 源码学习是对js的能力提升很有帮助的一个方法,废话不说,我们来开始学习啦 我们学习的源码是jquery-2.0.3已经不支持IE6,7,8了,因为可以少学很多hack和兼容的方法. jquery-2.0.3的代码结构如下 首先最外层为一个闭包, 代码执行的最后一句为window.$ = window.jquery = jquery 让闭包中的变量暴露倒全局中. 传参传入window是为了便于压缩 传入undefined是为了undifined被修改,他是window的属性,可以被修

Hadoop源码学习笔记(1) ——第二季开始——找到Main函数及读一读Configure类

Hadoop源码学习笔记(1) ——找到Main函数及读一读Configure类 前面在第一季中,我们简单地研究了下Hadoop是什么,怎么用.在这开源的大牛作品的诱惑下,接下来我们要研究一下它是如何实现的. 提前申明,本人是一直搞.net的,对java略为生疏,所以在学习该作品时,会时不时插入对java的学习,到时也会摆一些上来,包括一下设计模式之类的.欢迎高手指正. 整个学习过程,我们主要通过eclipse来学习,之前已经讲过如何在eclipse中搭建调试环境,这里就不多述了. 在之前源码初

HSQLDB源码学习——数据库安装启动及JDBC连接

HSQLDB 是一个轻量级的纯Java开发的开放源代码的关系数据库系统.因为HSQLDB的轻量(占用空间小),使用简单,支持内存运行方式等特点,HSQLDB被广泛用于开发环境和某些中小型系统中. 在http://sourceforge.net/projects/hsqldb/files/下载了HSQLDB 1.8.0版本.把下载的zip文件解压缩至任意目录例如c:\hsqldb1.8便完成安装. hsqldb有四种运行模式: 一.内存(Memory-Only)模式:所有数据都在内存里操作.应用程

lodash源码学习(10)

_.delay(func, wait, [args]) 延迟wait毫秒之后调用该函数,添加的参数为函数调用时的参数 //delay.js var baseDelay = require('./_baseDelay'),//baseDelay方法 baseRest = require('./_baseRest'),//创建使用rest参数方法 toNumber = require('./toNumber');//转化为数字 /** * * @param {Function} func 需要延迟执

lodash源码学习(2)

继续学习lodash,依然是数组的方法 “Array” Methods _.indexOf(array, value, [fromIndex=0]) 获取value在数组 array所在的索引值 使用 SameValueZero方式比较(第一个全等===的元素). 如果 fromIndex 值是负数, 则从array末尾起算 该方法依赖于strictIndexOf和baseIndexOf方法,先看它们的源码 //_strictIndexOf.js /** * _.indexOf的专业版本,对元素