boost::scoped_ptr和std::auto_ptr非常类似,是一个简单的智能指针,它能够保证在离开作用域后对象被自动释放。下列代码演示了该指针的基本应用:

#include <string>
#include <iostream>
#include <boost/scoped_ptr.hpp> class implementation
{
public:
~implementation() { std::cout <<"destroying implementation\n"; }
void do_something() { std::cout << "did something\n"; }
}; void test()
{
boost::scoped_ptr<implementation> impl(new implementation());
impl->do_something();
} void main()
{
std::cout<<"Test Begin ... \n";
test();
std::cout<<"Test End.\n";
}

该代码的输出结果是:

Test Begin ...
did something
destroying implementation
Test End.

可以看到:当implementation类离其开impl作用域的时候,会被自动删除,这样就会避免由于忘记手动调用delete而造成内存泄漏了。

boost::scoped_ptr特点:

boost::scoped_ptr的实现和std::auto_ptr非常类似,都是利用了一个栈上的对象去管理一个堆上的对象,从而使得堆上的对象随着栈上的对象销毁时自动删除。不同的是,boost::scoped_ptr有着更严格的使用限制——不能拷贝。这就意味着:boost::scoped_ptr指针是不能转换其所有权的。

  1. 不能转换所有权
    boost::scoped_ptr所管理的对象生命周期仅仅局限于一个区间(该指针所在的"{}"之间),无法传到区间之外,这就意味着boost::scoped_ptr对象是不能作为函数的返回值的(std::auto_ptr可以)。
  2. 不能共享所有权
    这点和std::auto_ptr类似。这个特点一方面使得该指针简单易用。另一方面也造成了功能的薄弱——不能用于stl的容器中。
  3. 不能用于管理数组对象
    由于boost::scoped_ptr是通过delete来删除所管理对象的,而数组对象必须通过deletep[]来删除,因此boost::scoped_ptr是不能管理数组对象的,如果要管理数组对象需要使用boost::scoped_array类。

boost::scoped_ptr的常用操作:

可以简化为如下形式:

namespace boost {

    template<typename T> class scoped_ptr : noncopyable {
public:
explicit scoped_ptr(T* p = );
~scoped_ptr(); void reset(T* p = ); T& operator*() const;
T* operator->() const;
T* get() const; void swap(scoped_ptr& b);
}; template<typename T>
void swap(scoped_ptr<T> & a, scoped_ptr<T> & b);
}

它的常用操作如下:

成员函数

功能

operator*()

以引用的形式访问所管理的对象的成员

operator->()

以指针的形式访问所管理的对象的成员

reset()

释放所管理的对象,管理另外一个对象

swap(scoped_ptr& b)

交换两个boost::scoped_ptr管理的对象

下列测试代码演示了这些功能函数的基本使用方法。

#include <string>
#include <iostream> #include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp> #include <boost/config.hpp>
#include <boost/detail/lightweight_test.hpp> void test()
{
// test scoped_ptr with a built-in type
long * lp = new long;
boost::scoped_ptr<long> sp ( lp );
BOOST_TEST( sp.get() == lp );
BOOST_TEST( lp == sp.get() );
BOOST_TEST( &*sp == lp ); *sp = 1234568901L;
BOOST_TEST( *sp == 1234568901L );
BOOST_TEST( *lp == 1234568901L ); long * lp2 = new long;
boost::scoped_ptr<long> sp2 ( lp2 ); sp.swap(sp2);
BOOST_TEST( sp.get() == lp2 );
BOOST_TEST( sp2.get() == lp ); sp.reset(NULL);
BOOST_TEST( sp.get() == NULL ); } void main()
{
test();
}

oost::scoped_ptr和std::auto_ptr的选取:

boost::scoped_ptr和std::auto_ptr的功能和操作都非常类似,如何在他们之间选取取决于是否需要转移所管理的对象的所有权(如是否需要作为函数的返回值)。如果没有这个需要的话,大可以使用boost::scoped_ptr,让编译器来进行更严格的检查,来发现一些不正确的赋值操作。

std::auto_ptr不能用在STL的container,为什么

http://bbs.csdn.net/topics/300233523

auto_ptr头文件<memory>

   STL中的auto_ptr指针是为了解决内存泄漏问题而设计的。它严格限制了指针拥有对指向对象的所有权。auto_ptr指针和普通指针的差别在于对指向对象所有权的处理不同。auto_ptr指针是“传递”所有权,而普通指针是“共享”所有权。看下面例子:
std::auto_ptr<int> p1(new int(24));
std::auto_ptr<int> p2;
int *q1 = new int(12);
int *q2;
p2 = p1;
q2 = q1;
    经过两次赋值后,对于auto_ptr,p1为NULL,*p2为24;对于普通指针,*p1, *p2均为12。第一次赋值,p1把指向对象的所有权传递给了p2, p1不再拥有指向对象的所有权。而第二次赋值,q2和q1共享了对同一对象的所有权。因此,对于auto_ptr,一个对象只可能被一个智能指针指向,这样可有效避免内存泄漏问题。但是同时会引起新问题。看下面例子:
template<class T>
void BadPrint(std::auto_ptr<T> p)
{
    if (p.get() == NULL)
    {
         std::cout<<NULL;
    }
    else
    {
         std::cout<<*p;
    }
}
    然后我如下使用BadPrint函数:
std::auto_ptr<int> q(new int(18));
BadPrint(q);
*q = 12;
     该程序并未像我们所期望的一样:*q的值为12,而是会出现runtime error,why?因为我们把q作为函数参数传给了BadPrint,因此传递完成后q不再拥有对指向对象的所有权,而函数内部的局部变量p会接管q所指向对象的所有权,当函数执行完毕退出时,p的生命期截止同时delete所指向对象。因此q实际变为NULL,所以出错。如何避免出错?使用auto_ptr的引用?即 void BadPrint(std::auto_ptr<T> &p)。这是相当糟糕的一种做法。对智能指针使用引用混淆了所有权的问题。它导致所有权有可能被传递了,也可能没有被传递。无论如何应当避免对auto_ptr使用引用。
     可见智能指针并非对任何情况都智能。使用auto_ptr要知道:
1. 智能指针不能共享指向对象的所有权
2. 智能指针不能指向数组。因为其实现中调用的是delete而非delete[]
3. 智能指针不是万能的
4. 智能指针不能作为容器类的元素。例如:
template<class T>
void container::insert(const T &value)
{
   ..........
   X = value;
   ..........
}
事实上在stl中,所有的container要内部拷贝所传参数的值时都是传的const类型的值。因此无法用auto_ptr传进去。
 
auto_ptr与scoped_ptr比较:

auto_ptr源代码:

template <typename _Tp> 
class auto_ptr 

private: 
    _Tp *m_ptr; 
public: 
    typedef _Tp elementType; 
 
    // object life cycle  
    explicit auto_ptr(elementType *p) throw():m_ptr(p) 
    { 
    } 
 
    auto_ptr(auto_ptr &a) throw():m_ptr(a.release()) 
    { 
    } 
 
    template <typename _Tp1> 
    auto_ptr(auto_ptr<_Tp1> &a) throw() : m_ptr(a.release()) 
    { 
    } 
 
    auto_ptr& operator= (auto_ptr& a) throw() 
    { 
        reset(a.release()); 
        return *this; 
   } 
 
    template <typename _Tp1> 
    auto_ptr& operator=(auto_ptr<_Tp1> &a) throw() 
    { 
        reset(a.release()); 
        return *this; 
    } 
 
    ~auto_ptr() 
    { 
        delete m_ptr; 
    } 
 
    // operator override  
    elementType& operator*() const throw() 
    { 
        assert(m_ptr != 0); 
        return *m_ptr; 
    } 
 
    elementType* operator->() const throw() 
    { 
        assert(m_ptr != 0); 
        return m_ptr; 
    } 
 
    // helper   
    elementType* get() const throw() 
    { 
        return m_ptr; 
    } 
 
    elementType* release() throw() 
    { 
        elementType *tmp = m_ptr; 
        m_ptr = 0; 
        return tmp; 
    } 
 
    void reset(elementType *p = 0) throw() 
    { 
        if (p != m_ptr) 
        { 
            delete m_ptr; 
            m_ptr = p; 
        } 
    } 
};

boost::scoped_ptr源代码:

#ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED

#include <boost/assert.hpp>
#include <boost/checked_delete.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

explicit scoped_ptr( std::auto_ptr<T> p ): px( p.release() ) // never throws
    {
#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
        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 // never throws
    {
        return px;
    }

// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>

void swap(scoped_ptr & b) // never throws
    {
        T * tmp = b.px;
        b.px = px;
        px = tmp;
    }
};

template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws
{
    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)
{
    return p.get();
}

} // namespace boost

#endif // #ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED

分析:

二者实现原理是相同的,都是通过创建一个类的对象调用类的析构函数来释放掉类的成员,但是scoped_ptr的安全性要高(不是指内存泄漏问题),scoped_ptr将拷贝构造写进私有,这就保证了使用scoped_ptr不可以转让,否者auto_ptr造成delete两次同一块内存,错误。以后在编码中,内存泄漏问题的关于指针可以通过使用上面两个类,但是对于使用上面两种类是好是坏,还是使用delete,看情况。

//@转载请链接相应地址http://blog.sina.com.cn/s/articlelist_2684002282_0_1.html

-----------------------------------

scoped_array

scoped_array使用起来很方便,轻巧,而且速度和原始指针相差无几. 而且更加安全..

scoped_array主要有以下几个特点;

1.构造函数接受的的指针必须是new[]返回的结果,而不能是new返回的结果.

2.没有*、->操作符的重载,因为scoped_array管理的不是一个普通的指针.

3.析构函数使用delete[]释放内存而不是用delete;

4.提供operator[]操作符,,因此我们可以像普通数组一样操作他,

5.没有begin\end类似于容器的迭代器操作函数.

#include <string>
#include <iostream>
#include<boost/scoped_array.hpp> #define MAX 10
using namespace std; int main()
{
boost::scoped_array<char> ptr;
ptr.reset(new char[MAX]); for(int i=;i<MAX;i++)
{
ptr[i]='a'+i;
cout<<ptr[i]<<endl;
}
}

需要动态分配数组时,通常最好用std::vector来实现,但是有两种情形看起来用数组更适合: 一种是为了优化,用vector多少有一些额外的内存和速度开销;另一种是为了某种原因,要求数组的大小必须是固定的。动态分配的数组会遇到与普通指针一样的危险,并且还多了一个(也是最常见的一个),那就是错误调用delete操作符而不是delete[]操作符来释放数组。我曾经在你想象不到的地方见到过这个错误,那也是它常被用到的地方,就是在你自己实现的容器类里!scoped_array 为数组做了scoped_ptr为单个对象指针所做的事情:它负责释放内存。区别只在于scoped_array 是用delete[] 操作符来做这件事的。

scoped_array是一个单独的类而不是scoped_ptr的一个特化,其原因是,因为不可能用元编程技术来区分指向单个对象的指针和指向数组的指针。不管如何努力,也没有人能发现一种可靠的方法,因为数组太容易退化为指针了,这使得没有类型信息可以表示它们是指向数组的。结果,只能由你来负责,使用scoped_array而不是scoped_ptr,就如你必须用delete[]操作符而不是用delete操作符一样。这样的好处是scoped_array 负责为你处理释放内存的事情,而你则告诉scoped_array 我们要处理的是数组,而不是裸指针。

scoped_array与scoped_ptr非常相似,不同的是它提供了operator[] 来模仿一个裸数组。

scoped_array 是比普通的动态分配数组更好用。它处理了动态分配数组的生存期管理问题,就如scoped_ptr管理对象指针的生存期一样。但是记住,多数情况下应该使用std::vector,它更灵活、更强大。只有当你需要确保数组的大小是固定的时候,才使用scoped_array 来替代 std::vector.

使用建议:

scoped_array使用起来很轻便,没有为程序增加额外的负担,它的速度与原始数组一样快,很适合习惯用new操作符在堆上分配内在的同仁,但scoped_array功能有限,不能动态增长,也没有迭代支持,不能搭配STL算法,仅有一个纯粹的数组接口。

需要动态数组的话尽量使用std::vector容器,相比之下它比scoped_array更灵活,而只付出了很小的代价。

  1. vector<int>  sa(100,2);
  2. sa[30] = sa[10] + sa[20];

很显然,std::vector更简洁,而且有丰富的成员函数来操作数据,易于维护。

除非对性能有非常苛刻的要求,或者编译器不支持标准库(比如某些嵌入式操作系统),否则不推荐使用scoped_array,它只是为了与老式的C风格代码兼容而使用的类,它的出现往往代表你的代码中存在隐患

auto_ptr实现:

http://www.cnblogs.com/-Lei/archive/2012/08/31/2664732.html

Boost scoped_ptr scoped_array 以及scoped_ptr与std::auto_ptr对比的更多相关文章

  1. 智能指针剖析(上)std::auto_ptr与boost::scoped_ptr

    1. 引入 C++语言中的动态内存分配没有自动回收机制,动态开辟的空间需要用户自己来维护,在出函数作用域或者程序正常退出前必须释放掉. 即程序员每次 new 出来的内存都要手动 delete,否则会造 ...

  2. C++智能指针剖析(上)std::auto_ptr与boost::scoped_ptr

    1. 引入 C++语言中的动态内存分配没有自动回收机制,动态开辟的空间需要用户自己来维护,在出函数作用域或者程序正常退出前必须释放掉. 即程序员每次 new 出来的内存都要手动 delete,否则会造 ...

  3. std::auto_ptr

    auto_ptr是C++标准库中(<utility>)为了解决资源泄漏的问题提供的一个智能指针类模板(注意:这只是一种简单的智能指针) auto_ptr的实现原理其实就是RAII,在构造的 ...

  4. C++安全异常std:auto_ptr

    auto_ptr它是C++标准库(<utility>)为了一个智能指针类模板来解决资源泄漏所提供的问题(注意:这只是一个简单的智能指针) auto_ptr在事实原则的实现RAII,对资源的 ...

  5. [3] 智能指针std::auto_ptr

    [1]std::auto_ptr 对于编译器来说,智能指针实质是一个栈对象,而并非指针类型. 智能指针通过构造函数获取堆内存的管理所有权,而在其生命期结束时,再通过析构函数释放由它所管理的堆内存. 所 ...

  6. 关于std:auto_ptr std:shared_ptr std:unique_ptr

    很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生成健壮的代码.本文阐述了如何正确 ...

  7. 「caffe编译bug」 undefined reference to `boost::match_results<__gnu_cxx::__normal_iterator<char const*, std::__cxx11

    CXX/LD -o .build_release/tools/test_net.binCXX/LD -o .build_release/tools/convert_annoset.binCXX/LD ...

  8. boost准模板库scoped_ptr指针的使用以及auto_ptr智能指针的对照

    首先我们看看scoped_ptr的基本使用,包括了swap(),get(),reset()的使用,重要的提醒是作用域结束的时候会自己主动析构,无需手动的释放资源: #include<boost/ ...

  9. C++ 智能指针 std::auto_ptr 分析

    背景介绍: RAll机制 定义一个类来封装资源的分配和释放,在构造函数中完成资源的分配和初始化,在析构函数中完成资源的清理,从而保证资源的正确初始化和清理 ps:智能指针就是RAll机制的一种应用,智 ...

随机推荐

  1. 可执行文件格式elf和bin

    区别 常用的可执行文件包含两类:原始二进制文件(bin)和可加载执行的二进制文件,在linux中可加载执行的二进制文件为elf文件. BIN文件是直接的二进制文件,内部没有地址标记.bin文件内部数据 ...

  2. phpcms 初次建站心得

    最近要给客户建个网站,考虑到效率问题,直接找了个开源的phpcms,(现在被收购了,以前的时候我还知道是个开源的).由于对这个东西不熟悉,原来就是了解一些,php的建站系统,php的MVC框架.故此, ...

  3. 'Neither SQLALCHEMY_DATABASE_URI nor SQLALCHEMY_BINDS is set.

    UserWarning: Neither SQLALCHEMY_DATABASE_URI nor SQLALCHEMY_BINDS is set. Defaulting SQLALCHEMY_DATA ...

  4. 关于MongoDB最大连接数的查看与修改

    一. MongoDB连接数 在Linux平台下,无论是64位或者32位的MongoDB默认最大连接数都是819,WIN平台不知道,估计也没有人在 WIN平台下使用MongoDB做生产环境 [root@ ...

  5. easyUI的column的field的颜色属性

     {field:'hasPrintStr',title:'状态',width:10,halign:'center',align:'right',styler: function(value,row,i ...

  6. GridView解决同一行item的高度不一样,如何同一行统一高度问题?

    问题描述: 有时我们使用GridView会面对类似这种情况. 这是是不是一脸愣逼,我们理想情况是把他变成这样 保证同一行的item都是一样高这样就美观许多了 注意:上面的两张图片是盗图,用来作为效果观 ...

  7. Oracle常用命令大全

    一.ORACLE的启动和关闭 1.在单机环境下 要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 su - oracle a.启动ORACLE系统 oracle>svrmgrl ...

  8. 目标跟踪之卡尔曼滤波---理解Kalman滤波的使用预测

    Kalman滤波简介 Kalman滤波是一种线性滤波与预测方法,原文为:A New Approach to Linear Filtering and Prediction Problems.文章推导很 ...

  9. 【BZOJ】3301: [USACO2011 Feb] Cow Line(康托展开)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3301 其实这一题很早就a过了,但是那时候看题解写完也是似懂非懂的.... 听zyf神犇说是康托展开, ...

  10. 【vijos】1790 拓扑编号(拓扑+贪心)

    https://vijos.org/p/1790 好神的贪心题.. 一开始我也想到了贪心,但是是错的..sad 就是因为每一个节点的编号与逆图的子树有关,且编号一定是>=子树的儿子+1的.但是想 ...