当前位置:文档之家› Boost智能指针

Boost智能指针

Boost使用笔记(Smart_ptr)概述Boost库是一个功能强大、构造精巧、跨平台、开源免费的C++程序库,提供了代码编写中所需要的几乎所有常见工具,例如智能指针、bind、正则表达式、xml解析等工具。

其代码以泛型编程为基础,且绝大部分代码放在扩展名为hpp的头文件中,以内联的方式引入到目标程序,因此Boost库几乎无需编译即可使用。

最新版的C++标准中已经将boost部分模块纳入其中,足见其功能的强大。

目前Boost库是除STL库以外最常用的C++代码库之一。

在实际开发中,Boost多用于应用软件和游戏编程,由于代码量相当庞大,且内部各模块互相引用牵连,致使使用Boost中很小的功能,也要将整个Boost库全部安装,应用上相对冗余,不过由于Boost以泛型编程为基础,实际编译到目标程序中的代码量并不大,且多为Inline形式,效率上也同样不差。

Boost是跨平台的,其代码支持Win、Linux、Vxworks等平台,由于精力和时间有限没有对完整的库在Vxworks下进行验证,经过试验的库有3个:●smart_ptr●xpressive●property_tree三个库在Vxworks6.4及Vxworks6.8上都做过实验,并且在板卡上试验了Boost的兼容性及性能。

在实验中smart_ptr库在Vxworks6.4及Vxworks6.8平台下均可编译执行,由于smart_ptr模块相对其他模块较为独立,现已将其从Boost库中全部抽取出来(大概218个文件)上传到Git中,可以在编码中独立使用。

https:///guolisen/BoostSmartPtr.git 需要注意的是BoostSmartPtr由Boost 1.43.0代码而来,目前只支持shared_ptr。

前面介绍过boost库代码互相牵连,即使加入一个weak_ptr也需要再加入关联的好几百个文件,因此为保证精简性没有将其加入。

xpressive 库是一个用来解析正则表达式的库,由于非常“高级”且庞大,在实验中只进行了基本的编译和使用,没有做过多的尝试。

xpressive 库接口简易,功能强大,但同样由于内部牵连过多,因此没能将其抽取出来。

property_tree库已经编译通过但使用中出现崩溃的情况,没有深究崩溃的原因(有可能是编译环境的问题,非代码本身问题),XML解析使用tinyXml已经完全满足要求。

智能指针在我们日常编码中经常使用到new关键字分配内存,被分配的内存需要在适当的时候调用delete关键字释放,否则可能造成内存泄露导致内存分配失败错误。

为了避免这样的错误人们发明了智能指针,其设计思想是管理内存生命周期,使那些从堆中分配的内存在不使用时自动被释放,程序员只需要知道在哪里分配内存,而不用担心是否忘记将其释放。

简单的智能指针原理请看下面代码:template<typename T>class simple_smart_ptr{public:simple_smart_ptr(T* mem_ptr):mPtr(mem_ptr) {assert(mPtr);std::cout <<"Ptr Create!"<< std::endl;};~simple_smart_ptr(){assert(mPtr);std::cout <<"Ptr Destory!"<< std::endl;delete mPtr;};T* operator-> () const{assert(mPtr);return mPtr;}private:T* mPtr;};class Test{public:void print(){std::cout <<"HeiHei!"<< std::endl;};};void TestFun(){simple_smart_ptr<Test> t(new Test);t->print();}int main()TestFun();return 0;}输出:Ptr Create!HeiHei!PtrDestory!上面是一个智能指针的原型代码,simple_smart_ptr在构造函数获取需要管理的堆指针,即new出来的指针地址。

当智能指针结束生命期后,析构函数被调用,被管理的内存被自动释放。

智能指针是一种防止内存泄露的有效手段,甚至可以说是大型软件开发的必用工具。

目前使用最广泛的智能指针是std::auto_ptr和boost::smart_ptr,std::auto_ptr出自标准库,不支持引用计数,与STL容器不兼容,在使用上有一定局限。

boost::smart_ptr是Boost库的一部分,包括scoped_ptr、shared_ptr、weak_ptr等。

Boost的智能指针代码非常优秀,且已经收录到C++最新标准之中,可以放心使用,在下面的章节中会逐步为大家介绍。

std::auto_ptrstd::auto_ptr是标准库中提供的一种智能指针,实现了最基本的内存自动管理机制,其使用方法和上一节用到的simple_smart_ptr基本相同。

#include<memory>class Test{public:void print(){std::cout <<"HeiHei!"<< std::endl;};};int main(){std::auto_ptr<Test> at(new Test);at->print();return 0;}输出:HeiHei!例子程序中使用std::auto_ptr管理在堆中分配的Test对象,当main函数返回的时候,at局部变量结束生命期,析构函数被调用,Test对象的内存自动释放。

由于std::auto_ptr没有实现引用计数机制,如果出现两个std::auto_ptr同时引用同一片内存,将会出现毁灭性的结果。

因为此时若其中任何一个指针退出生存周期将会释放对应内存区域,与他拥有相同内存指针的另一个std::auto_ptr将变成“野指针”,若此std::auto_ptr 退出生命周期系统将崩溃。

为了解决这样的问题std::auto_ptr引入了一种叫做“拥有权”的概念,每个需要被管理的原始内存指针只对应一个std::auto_ptr,同一时间只有一个std::auto_ptr对此原始指针有“拥有权”。

若对此std::auto_ptr执行复制或将其赋值给其他std::auto_ptr,那么原始指针的“拥有权”将转移到被复制的新std::auto_ptr中(即新std::auto_ptr将拥有原始指针,被复制的std::auto_ptr将指向NULL)。

看下面例子:void testFun(std::auto_ptr<Test> p){p->print();}int main(){/////////////////////////////////////////////////std::auto_ptr<Test> b(new Test);std::auto_ptr<Test> c;b->print();c = b; //使用operator=使拥有权转移,b不再拥有Test的指针且指向NULLc->print();b->print(); //这里系统将奔溃/////////////////////////////////////////////////std::auto_ptr<Test> d(new Test);d->print();std::auto_ptr<Test> e(d); //使用构造函数使拥有权转移,d不再拥有Test 的指针且指向NULLe->print();d->print(); //这里系统将奔溃/////////////////////////////////////////////////std::auto_ptr<Test> f(new Test);f->print();testFun(f); //使用拷贝构造函数使拥有权转移,f不再拥有Test的指针且指向NULLf->print(); //这里系统将奔溃return 0;由上面例子可以看到,当std::auto_ptr发生复制,构造,拷贝构造时std::auto_ptr对原始指针的拥有权将转移,自身将指向NULL,此时再引用此std::auto_ptr进行指针操作时系统将会崩溃(此时已经指向NULL)。

拥有权的设计避免了std::auto_ptr指向共享区域从而导致二次释放的问题,同时也规避了线程安全问题(无共享区域)。

但std::auto_ptr在使用中还是有许多坑需要注意:1.std::auto_ptr用作函数的参数或返回值时需要格外小心,当std::auto_ptr做函数的非引用参数时,由于会调用拷贝构造函数,因此会发生拥有权的转移,此时做参数的std::auto_ptr将指向NULL,若此时再次引用将产生崩溃voidtestFun(std::auto_ptr<Test> p){p->print();}int main(){Test* pa = new Test;std::auto_ptr<Test>at(pa);at->print();testFun(at);//拥有权转移at->print();//拥有权已经转移,再次引用将崩溃return 0;}2.std::auto_ptr本身与STL容器不兼容,因此不能将其放到std::vector、std::list、std::map 中使用。

(但是VC6貌似可以编译通过,足见VC6已经不适合现代开发了,继续使用将造成巨大的移植隐患)3.std::auto_ptr不能管理数组指针,因为在析构的时候std::auto_ptr使用的是delete 而不是delete []可以看到,使用std::auto_ptr还是有很多不方便的地方,且存在很多极容易出错的坑,这也是std::auto_ptr没有被大规模应用的原因,在下一节中我们将介绍Boost的智能指针shared_ptr,shared_ptr是一种建立在引用计数框架下的智能指针,且效率及稳定性极高,不存在兼容性的问题,是应用最广泛的智能指针之一。

相关主题