Boost库的大部分组件(90%左右),不需要进行编译,直接包含头文件即可使用。
#include <boost/logic/tribool.hpp>
using namespace std;
www.boost.org
配合boost库工作
可移植性高,几乎可以配合市面上所有的操作系统合编译器来使用
如果想要深入了解,推荐大家看一下《Boost完全开发手册这本书》,虽然是十年前的老书,但有诸多可以复用的经验,读后使人受益匪浅。
由于指针的灵活性与复杂性,C++在使用指针不当时,会导致内存泄漏、野指针、访问越界等一系列的问题。
C++提供了auto_ptr智能指针,但仍有不足。
boost库中提供了想java垃圾回收机制一样的一套高效的管理内存方式。
在使用资源的类的构造函数中申请资源,在相应的析构函数中释放资源。
在声明栈上局部变量时申请的资源,可以在离开作用域后自动释放,而使用new申请的资源,需要程序员显式的进行相应的delete操作才能释放,这就造成了内存泄漏的安全隐患。
在退出作用域时,不管是正常退出还是异常退出,都自动调用delete释放在堆中动态申请的资源。
智能指针有很多种,例如:
std::auto_prt
int main()
{
auto_ptr < class_need_resource > p1 (new class_need_resource);
auto_ptr <demo_class> p2(demo_class.creat());
} // 离开作用域后,p1,p2自动析构,释放占用的内存空间
遗憾的是,C++标准库并没有覆盖智能指针的全部领域,特别是引用计数型智能指针。
boost.smart_ptr库是对C++98标准的一个绝对补充,包含了六种智能指针:
以上六种智能指针,都是轻量级的组件,速度与原始指针相差无几,对于所指向的类型T也仅有一个很小且很合理的要求:类型T不能抛出异常。
如何使用:
include <boost/smart_prt>
using namespace boost;
类似auto_ptr的智能指针,保证动态创建的对象在任何时候都能被正确的删除。
scoped_ptr的所有权限制更加严格,不能转让,一旦scoped_ptr获得了对象的所有权,你就不能从它那里收回来。
scoped_ptr同时把拷贝构造函数和赋值操作符都声明为私有,禁止对指针的赋值操作,保证了它管理的指针不能被转让所有权。
成员函数reset的功能是重置scope的_ptr,这违背了设计的初衷。
非必须的情况下,尽少使用这种用法。
scoped_ptr重载了运算符*和运算符->,来模仿被代理的原始指针的行为,便于将Scoped_ptr对象如同原始指针对象一样来使用。如果,scoped_ptr保存了空指针,则此行为未定义。
scoped_ptr指针不能进行比较操作,因为==和!=运算符都已经被声明为私有,但是提供了一种在bool语境中自动转化为bool值的用法,通过这一用法可以判断指针是否为空。
成员函数swap用来交换两个指针的值,操作高效,被用于实现reset函数。
成员函数get用来返回此局部指针所对应的原始指针,一般用于如底层是C语音必须需要原始指针的场景等。
注意,千万不要对返回的指针进行delete操作。
否则,程序会面临崩溃的危险。
scoped_ptr和auto_ptr的用法基本一致,大多数情况下可以相互替换,它可以从auto_ptr获得指针的管理权——同时auto_ptr失去指针的管理权。
与auto_ptr一样,两者都不能用作容器的元素,不过原因不同。
auto_ptr是因为它的转移语义,而scoped_ptr是因为他不能拷贝和赋值,不符合容器对元素的要求。
auto_ptr的指针所有权是可以转移的,可以在函数间传递,同一时刻只能有一个auto_ptr来进行管理。
而scoped_ptr因为私有化了赋值和拷贝操作,指针所有权不能转移。
scoped_array弥补了标准库中没有指向数组的智能指针的遗憾。
构造函数接受的指针必须是new【】的结果
重载了【】运算符,可以像普通数组一样使用下标访问元素,但越界时会发生意想不到的错误。
但不能使用*和->运算符,因为没有定义。
只能在声明的作用域内使用,不能拷贝和赋值。
由于并未定义很多操作,使用scoped_array与使用正常数组速度一样快,但是不能作为函数和容器等的接口,也不能动态增长。
因此,如果要使用动态数组的话,尽量使用std::vector,它只引入了很小的开销,提供了更高的安全性和灵活性。
shared_ptr是最像指针的智能指针,是boost.smart_ptr库中,最有价值、最重要的组成部分。
引用计数型的智能指针,可以被自由的拷贝和赋值,在任意的地方共享它,当没有代码使用它(引用计数为0时),才自动删除被包装的对象。
shared_ptr可以安全的放到标准的容器中,作为容器的元素。
shared_ptr与scoped_ptr一样都是管理new动态分配对象的智能指针,因此功能上有许多的相似之处。
shared_ptr不但有正常的赋值与拷贝语义,而且可以进行比较操作。
无参数的shared_ptr创建一个持有空指针的shared_ptr。
shared_ptr(Y * p) 获得指向类型T的p指针的管理权,同时引用计数置为1。
其中类型Y必须能转化为类型T。
shared_ptr ( shared_ptr const & r), 从另一个shared_ptr获得指针的管理权,同时引用计数加1,结果是两个shared_ptr指针共享一个指针的管理权。
shared_ptr(std::auto_ptr < Y > & r),从一个auto_ptr获得指针的管理权,引用计数置为1,同时auto_ptr失去指针的管理权。
“=” 赋值运算符,对于对象shared_ptr和auto_ptr,结果同构造函数。
当然,还有特殊的shared_ptr(Y * p,D d),第二个参数指定了析构时的一些特性,之后再做介绍。
对于不带参数的reset(),效果是让引用数减1.
带参数的reset()函数在原指针引用计数减1的同事,改为管理另一个指针,效果类比同样形式的构造函数。
unique()返回当前指针是否引用了,如果引用了,则返回true,否则,返回false,高效操作。
use_count() 较为低效率的操作,返回计数引用的指针数量,甚至有时候是不可用的。
比较运算基于内部的指针,如a.get() == b.get().
还提供了唯一可以使用的比较运算符 " < ",因为提供了 " < " 操作,因此可以被用于某些内部的容器,比较set和map等等。
在编写基于虚函数的多态代码时,指针的类型转换很重要,比如把一个基类指针转化为一个子类的指针,或者反过来。
但是对于shared_ptr不能使用诸如
static_cast<T*> (p.get())
的形式。
而要使用:
static_pointer_cast<T> ()
const_pointer_cast<T> ()
dynamic_pointer_cast<T> ()
分别对应标准的转型操作符:
static_cast<T> ()
const_cast<T> ()
dynamic_cast<T> ()
但以上操作符返回的类型都是shared_ptr。
#include <boost/make_shared.hpp>
make_shared()函数可以接收最多十个参数,然后把他们传递给类型T的构造函数,创建一个shared_ptr对象并返回。
make_shared()函数要比直接创建shared_ptr对象的方式更为高效,因为他内部仅仅分配了一次内存,消除了shared_ptr构造时的开销。
#include <vector>
#include <boost/smart_ptr.hpp>
#include <boost/make_shared.hpp>
using namespace boost;
int main()
{
shared_ptr<string> sp = make_shared<string>("Hello make_shared make me.");
shared_ptr<std::vector<int> > sp_vector = make_shared<std::vector<int> > (10, 2);
assert(spv->size() == 10);
}
桥接模式(bridge)是一种结构型的设计模式,把类之间的具体实现细节隐藏起来,以达到最小耦合的目的。
在具体实践中,桥接模式也被称为pimpl或者handle/body惯用法,可以将文件的依赖关系降到最小,减少编译时间,可以不利用虚函数便能实现多态。
shared_ptr<FILE> fp(fopen("./try.txt", 'r'), fclose);
当离开作用域时,shared_ptr自动调用fclose来关闭文件。
用法如同scoped_ptr,可以考虑更为安全的vecto,这里不做详细介绍。
协助shared_ptr使用,像旁观者一样观测资源的使用情况。
weak_ptr不影响引用计数。
获取this指针的shared_ptr,使对象产生shared_ptr对象管理自己。
对象使用weak_ptr观测this指针,不影响计数,在需要的时候调用lock()函数返回shared_ptr供外界使用。
简要介绍如上,如果要深入了解的话,可以继续翻阅书籍的相关章节。
侵入式的引用计数型指针,用于如下场景:
应用较少,只做简要介绍,如果需要的时候,再去深入学习。