智能指针系列

Boost中提供的5类智能指针。分别是:

l        scoped_ptr           独占的指针

l        scoped_array       独占的数组

l        shared_ptr            引用计数指针

l        shared_array         引用计数数组

l        weak_ptr             shared_ptr的一个弱指针(不参与引用计数)

l        intrusive_ptr         自定义的引用计数指针

scoped_ptr和scoped_array

对于scoped_ptr和scoped_array是不可以拷贝构造和赋值的(拷贝构造函数和operator=都是私有成员)。所以它们不像auto_ptr那样传递指针的拥有权,而是独占拥有权,直至对象的销毁(当scoped_ptr和scropted_array析构的时候,所指向的对象也会被析构)。

构造:

scoped_ptr<int> a(new int);

scoped_ptr<int> b;

scoped_array<int> c(new int[100]);

scoped_array<int> d;

scoped_ptr使用new T或者是NULL来初始化对象。scoped_array使用new T[]或者NULL来初始化对象。

它们的默认构造函数,是使用NULL来初始化。

访问:

scoped_ptr重载了operator*和operator->操作符,而scoped_array重载了operator[]下标运算符。通过这几个操作符来操作它们所指向的对象。它们都可以通过T* get()成员函数得到原始的指针。

例如:

scoped_array<char> str(new char[100]);

strcpy(str.get(),"hello");

cout<<str[0]<<str[4]<<endl;//输出ho

void reset(T * p = 0)

reset用于重置指针指向的对象,当调用reset的时候scoped_ptr或scoped_array会先删除原来指向的对象(如果不是指向NULL的话)。reset的参数和它们构造函数的要求是一样的,必须是new T(或new T[])或者是NULL。

swap

swap全局函数和swap成员函数,交换两个智能指针指向的对象。例如:

scoped_ptr<int> a(new int);//a指向一个int

scoped_ptr<int> b;//b指向NULL

swap(a,b);//这时,a指向NULL,b指向一个int

bool

scoped_ptr和scoped_array可以隐式的转换为bool类型,当指向NULL的时候返回false,否则返回true。

类型

scoped_ptr<T>和scoped_array<T>中的类型T不能是void类型。

并且scoped_ptr<T>和scoped_ptr<U>不存在类型转换,即使T和U是可以转换的,scoped_ptr<T>和scoped_ptr<const T>也不能转换。

shared_ptr和shared_array

shared_ptr和shared_array是引用计数的智能指针。

下面仅仅介绍shared_ptr的使用。。。剩余内容参考 http://hi.baidu.com/vicehunter/blog/item/ab6d7300ea1cfb0f1c958370.html


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

boost::scoped_ptrstd::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->()

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

get()

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

swap(scoped_ptr& b)

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

 

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

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

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

auto_ptr 和 scoped_ptr比较和区别,深入理解

分类: boost    1589人阅读 评论(0) 收藏 举报

#include "boost/scoped_ptr.hpp"
#include <iostream>
#include <memory>//contain auto_ptr 
using namespace std;
using  boost::scoped_ptr;

int main(int argc, char* argv[])
{

 scoped_ptr<int > sp( new int(10) ) , sp2;
 //sp = new int(10)
 //error,因为拷贝构造函数和赋值构造函数都是私有的
 //
 cout<< *sp<<endl;

//sp2=sp;  //error
 int *p=sp.get(); //不会导致sp失去空间的占有权
 //delete p ;//将导致错误,因为sp是分配的空间的所有者,只有它才有权利进行释放
 *p = 20;
 cout<< *sp<<endl;
 
 auto_ptr<int> ap(new int(1)) ,ap2;
 //ap = new int(1); //error
 ap2 = ap ; //ap将失去分配的空间的所有权
 int *p2 = ap2.get();//不会导致ap2失去空间的占有权
 *p2=100;
 //delete p2 ;//将导致错误,因为ap2是分配的空间的所有者,只有它才有权利进行释放
 return 0;
}

/////////////////////////////////////////////////////

智能指针类其实包含有几个数据成员其中一个就是所有权标记,另外一个就是指向动态分配的空间的地址。

1.只有对这个动态分配的空间拥有所有权的指针或者智能指针对象才有权利去释放这个空间。

因为如果使用指针的话没有所有权保护,所以虽然原则上是拥有所有权的才能释放但是如果是使用指针 就没办法确定一个指针是否占有所有权。所以不建议这么做。

//所有权与使用权分离。有使用权不一定有所有权!

另外智能指针类可以通过构造函数的访问属性和参数特性来禁止某些操作或允许某些操作。比如把重载赋值为私有来禁止赋值,把拷贝构造函数设置为私有来禁止拷贝。

2.对于智能指针而言get操作智能取得动态分配的空间的地址。而不能使智能指针失去所有权

3.一个动态分配的空间在只有一个所有权并且在某一个只能有一个所有者。但可以有多个使用者。

使用者可以对空间的内容进行赋值,但不允许进行释放操作。

auto_ptr代表的动态分配的空间的所有权是可以转移( 通过赋值)的。

scoped_ptr代表的动态分配的空间的所有权则不能转移(重载赋值为私有来禁止赋值,把拷贝构造函数设置为私有来禁止拷贝。)!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Solmyr 的小品文系列之五:垃圾收集    什么是智能指针


阅读更多
文章标签: null delete 编译器 c
个人分类: 重构C/C++
上一篇std::set||std::deque||std::map
下一篇【WebRTC基础系列】Mid-call features
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭