boost::shared_ptr<int> sp(new int(10)); //一个指向整数的shared_ptrassert(sp.unique()); //如今shared_ptr是指针的惟一持有者
boost::shared_ptr<int> sp2 = sp; //第二个shared_ptr,拷贝构造函数assert(sp == sp2 && sp.use_count() == 2); //两个shared_ptr相等,指向同一个对象,引用计数为2
*sp2 = 100; //使用解引用操做符修改被指对象
assert(*sp == 100); //另外一个shared_ptr也同时被修改
sp.reset(); //中止shared_ptr的使用,引用计数减一
assert(!sp); //sp再也不持有任何指针(空指针)
assert(sp2.use_count() == 1); //sp2引用计数变为1
sp.reset(new int(20)); //sp管理一个新对象assert(*sp == 20);
有两种方式能够将shared_ptr应用于标准容器(或者容器适配器等其余容器)。程序员
一种用法是将容器做为shared_ptr管理的对象,如shared_ptr<list<T> >,使容器能够被安全地共享,用法与普通shared_ptr没有区别,咱们再也不讨论。编程
另外一种用法是将shared_ptr做为容器的元素,如vector<shared_ptr<T> >,由于shared_ptr支持拷贝语义和比较操做,符合标准容器对元素的要求,因此能够实如今容器中安全地容纳元素的指针而不是拷贝。windows
标准容器不能容纳auto_ptr,这是C++标准特别规定的(读者永远也不要有这种想法)。标准容器也不能容纳scoped_ptr,由于scoped_ptr不能拷贝和赋值。标准容器能够容纳原始指针,但这就丧失了容器的许多好处,由于标准容器没法自动管理类型为指针的元素,必须编写额外的大量代码来保证指针最终被正确删除,这一般很麻烦很难实现。安全
存储shared_ptr的容器与存储原始指针的容器功能几乎同样,但shared_ptr为程序员作了指针的管理工做,能够任意使用shared_ptr而不用担忧资源泄漏。函数
#include <boost/make_shared.hpp>int main()
{typedef vector<shared_ptr<int> > vs; //一个持有shared_ptr的标准容器类型vs v(10); //声明一个拥有10个元素的容器,元素被初始化为空指针
int i = 0;
for (vs::iterator pos = v.begin(); pos != v.end(); ++pos)
{(*pos) = make_shared<int>(++i); //使用工厂函数赋值cout << *(*pos) << ", "; //输出值}cout << endl;shared_ptr<int> p = v[9];
*p = 100;cout << *v[9] << endl;}
这段代码须要注意的是迭代器和operator[]的用法,由于容器内存储的是shared_ptr,咱们必须对迭代器pos使用一次解引用操做符*以得到shared_ptr,而后再对shared_ptr使用解引用操做符*才能操做真正的值。*(*pos)也能够直接写成**pos,但前者更清晰,后者很容易让人迷惑。vector的operator[]用法与迭代器相似,也须要使用*获取真正的值。this
为何要使用enable_shared_from_this,或许你对这个类感到很迷惑,先看看下面这种状况:spa
class MyPoint
{public:
MyPoint(){std::cout << "MyPoint" << std::endl;}
~MyPoint(){std::cout << "~MyPoint" << std::endl;}
//返回this的函数
boost::shared_ptr<MyPoint> GetPoint(){return boost::shared_ptr<MyPoint>(this); //错误,将返回一个新的引用计数}};int _tmain(int argc, _TCHAR* argv[]){boost::shared_ptr<MyPoint> p1(new MyPoint);
boost::shared_ptr<MyPoint> p2 = p1->GetPoint();std::cout << p1.use_count() << "," << p2.use_count() << std::endl; //输出引用计数状况p1.reset(); //内存将被释放
}
咱们获得的答案将是:线程
MyPoint
1,1
~MyPoint指针
怎么正确的返回this呢,那么就须要借助enable_shared_from_this了,引入enable_shared_from_this的缘由是能够实现返回值为指向该类自己的shared_ptrcode
正确的写法应该是这样的:
class MyPoint : public boost::enable_shared_from_this<MyPoint>{public:
MyPoint(){std::cout << "MyPoint" << std::endl;}
~MyPoint(){std::cout << "~MyPoint" << std::endl;}
//返回this的函数
boost::shared_ptr<MyPoint> GetPoint(){return shared_from_this();
}};int _tmain(int argc, _TCHAR* argv[]){boost::shared_ptr<MyPoint> p1(new MyPoint);
boost::shared_ptr<MyPoint> p2 = p1->GetPoint();std::cout << p1.use_count() << "," << p2.use_count() << std::endl; //输出引用计数状况p1.reset(); //内存将被释放
}
当你在使用windows API函数进行编程时,你最烦的或许就是怎么保证申请的内核对象是否关闭,考虑一下代码:
int *p = (int*) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(p) );//业务处理
//......
HeapFree( GetProcessHeap(), 0, p );
对象不能经过delete来删除,而是一个释放函数,shared_ptr可否胜任呢,答案是确定的。
int *p = (int*) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(p) );//此处使用了lambda表达式,须要vs2010或更高版本的支持
boost::shared_ptr<int> ptr(p, [](int *p){HeapFree( GetProcessHeap(), 0, p );});
下面实现一个线程类,在线程运行结束时,可以自行清理本身的内存
#include <set>#include <Windows.h>#include <boost/thread.hpp>class MySelf;
std::set< boost::shared_ptr<MySelf> > myList;boost::thread *ptrTh;class MySelf: public boost::enable_shared_from_this<MySelf>{public:
MySelf(){printf("MySelf\n");
}void StartThread()
{//启动一个线程
ptrTh = new boost::thread(&MySelf::Run, this);}void Run()
{//线程任务函数
Sleep(5000);printf("stop thread\n");
Stop();}void Stop()
{//删除本身
myList.erase(shared_from_this());}~MySelf(){printf("~MySelf\n");
}};void TestSharePtr()
{boost::shared_ptr<MySelf> ptr1(new MySelf);
//保存到list中
myList.insert(ptr1);ptr1->StartThread();}