Boost scoped_ptr scoped_array 以及scoped_ptr与std::auto_ptr对比

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 = 0);
        ~scoped_ptr(); 

        void reset(T* p = 0); 

        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传进去。

参考:http://blog.sina.com.cn/s/blog_46d185020100026b.html

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=0;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

时间: 2024-10-10 06:31:58

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

boost库学习之 scoped_ptr scoped_array

boost.smart_ptr库提供了六种智能指针:scoped_ptr.scoped_array.shared_ptr.shared_array.week_ptr和intrusive_ptr. 说到智能指针,我们会想到c++98标准中的自动指针auto_ptr. auto_ptr获取指针所有权后,离开作用域时自动释放该指针指向的堆内存.也可以转移指针的所有权. auto_ptr<A> ap_a1(new A); auto_ptr<A> ap_a2(ap_a1); //发生所有权转

Boost源码学习---scoped_ptr.hpp

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

【c++】模拟实现boost库里的scoped_ptr

//模拟实现boost下的scoped_ptr #include <iostream> #include <assert.h> using namespace std; template <class T> class scoped_ptr { private: T * px; scoped_ptr(scoped_ptr const &); scoped_ptr& operator=(scoped_ptr const &); void opera

智能指针 std::auto_ptr 和 shared_ptr

需要注意: auto_ptr 类可以用于管理由 new 分配的单个对象,但是无法管理动态分配的数组(我们通常不会使用数组,而是使用 vector 代替数组).auto_ptr 在拷贝和赋值的时候有不寻常的行为,因此 auto_ptrs 不能被保存在 stl 的容器中.当 auto_ptr 离开了自己的作用域或者被销毁,由 auto_ptr 管理的对象也会被销毁. 使用std::auto_ptr需要的头文件: #include <memory> // 示例 1(b): 安全代码, 使用了auto

C++安全异常std:auto_ptr

auto_ptr它是C++标准库(<utility>)为了一个智能指针类模板来解决资源泄漏所提供的问题(注意:这只是一个简单的智能指针) auto_ptr在事实原则的实现RAII,对资源的访问,在施工时间.释放资源时,析构函数,而相关的指针操作超载.使用起来就像普通的指针. std::auto_ptr<ClassA> pa(new ClassA); 非常多人听说过标准auto_ptr智能指针机制,但并非每一个人都天天使用它.这真是个遗憾.由于auto_ptr优雅地攻克了C++设计和

std::auto_ptr

1, auto_ptr类 auto_ptr是一个模板类,定义如下: template <typename Type> class auto_ptr {...}: 它存储的是一个指向Type的指针. 顾名思义,auto_ptr是一种智能指针,它包含一个动态分配内存的指针,并在它生命周期结束的时候,销毁包含的指针所指向的内存. 例1: void f() { Type* pt(new Type); //一些代码... delete pt; } 这样的代码很常见,但它有可能造成内存泄露.首先你用了ne

(转)剖析C++标准库智能指针(std::auto_ptr)

不可否认,资源泄露(resource leak)曾经是C++程序的一大噩梦.垃圾回收 机制(Garbage Collection)一时颇受注目.然而垃圾自动回收机制并不能 满足内存管理的即时性和可视性,往往使高傲的程序设计者感到不自在. 况且,C++实现没有引入这种机制.在探索中,C++程序员创造了锋利的 "Smart Pointer".一定程度上,解决了资源泄露问题. 也许,经常的,你会写这样的代码: //x拟为class: // class x{ // public: // int

关于std:auto_ptr std:shared_ptr std:unique_ptr

很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生成健壮的代码.本文阐述了如何正确运用auto_ptr来让你的代码更加安全——以及如何避免对auto_ptr危险但常见的误用,这些误用会引发间断性发作.难以诊断的bug. 1.为什么称它为“自动”指针?auto_ptr只是众多可能的智能指针之一.许多商业库提供了更复杂的智能指针,用途广泛而令人惊异,从管理引用的数量到提供先进的代理服

C++中的智能指针(一):std::auto_ptr&lt;class T&gt; - &lt;memory&gt;

一:内存泄漏的问题 考虑如下的程序 void func() { ClassA *a = new ClassA; ... delete a; } 应该使用delete语句以保证new分配的空间一定会被释放.我几乎总会忘记delete语句,尤其函数要写return语句时,更容易忘记. 另外即使你加上了delete语句,你也无法完全避免空间无法释放的问题(这种问题的统一叫法:内存泄漏). void func() { ClassA *a = new ClassA; ... //产生异常 delete a