您的位置:首页 > 运维架构

Boost学习笔记----SmartPointer之Boost::scoped_ptr

2009-12-10 22:28 489 查看
声明:欢迎任何人和组织转载本blog中文章,但必须标记文章原始链接和作者信息。

本文链接:http://blog.csdn.net/li_007/archive/2009/12/11/4982419.aspx

.aspx">

开拓进取的小乌龟------->CSDN点滴点点滴滴Blog

很久之前就看了一些Boost的介绍,也一直在断断续续地关注着它,可就是没有去学习下或者写段代码来验证下。终于在一年到底的时候,静下来买回来《Beyond The C++ Standard Library--An Introduction to Boost》这本大作,安静地看看Boost的真面目,也亲身体会下Boost的安全性,高效,实用(当然是相比较STL而言拉)。
char * p = new char[10];
memset(p, 0, 10);
memcpy_s(p, 10, "Welcome", sizeof("Welcome"));
char * AnotherP = p;
delete []AnotherP;
AnotherP = NULL;


很简单的一段代码吧,可是在这里我只是对p进行了一次赋值,如果我进行了很多次赋值,100次,甚至更多,其实这在一个项目中是很有可能。这个时候我们怎么去delete来释放stack,很容易让我们多次delete而引发exception。或者最后很多人自己都糊涂了,根本就不知道自己到底释放了没有,并且不合时宜的delete更会引发exception。当然解决办法就已使用引用计数。

好了言归正传,来说说Boost::scoped_ptr这个Smart Pointer。其实在STL中也有智能指针,std::auto_ptr,它可以解决我们delete的问题,可以自动帮助我们释放stack,特别是在异常的时候,可以帮助我们正确释放stack。但是std::auto_ptr也有自己缺点,比如它对其他的stl的支持不好(大部分时候编译都通不过的)。boost中的智能指针就是为了弥补等等这些缺点而设计的,在boost中有scoped_ptr、scoped_array、shared_ptr和shared_array这四个智能指针,后面的学习笔记中会慢慢介绍。

scoped_ptr是一个轻量级的smart pointer实现,它拥有着和auto_ptr类似的功能,都是为了正确地帮助我们释放动态分配的对象,但是它也和auto_ptr有着很大的区别。scoped_ptr假定它对它指向的对象拥有所有权,并且在任何时候都不会意外放弃所有权。既然如此,scoped_ptr就肯定不可能进行赋值或者被复制了,但是auto_ptr是可以做这些操作的,所以在真正的应用上我们要根据实际来选择(但是我觉得可以基本放弃stl的auto_ptr了)。看看scoped_ptr的定义,如下:

namespace boost {
template<class T> class scoped_ptr : noncopyable {
public:
typedef T element_type;
explicit scoped_ptr(T * p = 0); // never throws
~scoped_ptr(); // never throws
void reset(T * p = 0); // never throws
T & operator*() const; // never throws
T * operator->() const; // never throws
T * get() const; // never throws

operator unspecified-bool-type() const; // never throws
void swap(scoped_ptr & b); // never throws
};
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
}


发现了一个规律就是所有实现都不抛出异常。特别是*和->操作符的重载,使得我们可以像使用普通的指针一样简单方便,由于scoped_ptr是轻量级的,所以它不会增加代码,也不会使Application运行变慢,它会让我们的code更健壮,更易于维护。

reset成员函数的作用是重置scoped_ptr,也即是删除scoped_ptr所存储的指针,然后保存p。在实际的应用中我们应该尽量少用这个函数或者不用。

get成员函数的作用是返回它所存储的指针,我们同样应该少用这个函数,多使用scoped_ptr为我们重载的操作符。get函数可以让我们操作裸指针,这是危险的。

#include "Boost/scoped_ptr.hpp"
#include <string>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
boost::scoped_ptr<std::string> bsPointer(new std::string("Use scoped_ptr often."));
if (bsPointer)
{
std::cout<<*(bsPointer.get())<<" --> "<<bsPointer->size()<<std::endl;
}
bsPointer->clear();
*bsPointer = "Acts just like a pointer!!!";
// 编译会通不过的,因为scoped_ptr的不可复制和赋值
//boost::scoped_ptr<std::string> bsPointer1 = bsPointer;
std::auto_ptr<std::string> autoPointer(new std::string("Welcome to china!"));
std::auto_ptr<std::string> autoPointer1 = autoPointer;
return 0;
}


在上面的example中,我们看到scoped_ptr的使用像普通指针一样,没有什么区别。而且是不可以复制或者赋值的,但是auto_ptr就不同了,它可以通过赋值来构造也可以通过复制来赋值的。但是在上面的赋值之后,autoPointer就只剩下一个空指针。

再次强调我们要少用get函数,比如在上面的example中,bsPointer在调用了get函数后,会得到一个裸指针,它指向了“Use scoped_ptr often.”内存块。如果我们不小心释放了这个裸指针,在scoped_ptr自己再次释放的时候会出现错误,同样不要把它再次赋值给另外的scoped_ptr,这样也会产生多次释放的错误。

最后结合平时编程遇到的问题,总结哈这个智能指针的使用:

1、在有可能抛出异常的作用域中。

2、函数中存在多条控制路径时

3、动态分配的对象的生命周期可以限定在一个特定的作用域范围内时

4、考虑异常安全的时候

PS:其实我希望有可能尽量少用或者不用auto_ptr(c++ox标准委员会已经接纳了boost的smart pointer)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: