3.4.2 操作函数
shared_ptr与scoped_ptr同样是用于管理new动态分配对象的智能指针,因此功能上有很多相似之处:它们都重载了*和->操作符以模仿原始指针的行为,提供隐式bool类型转换以判断指针的有效性,get()可以得到原始指针,并且没有提供指针算术操作。例如:
- shared_ptr<int> spi(new int); //一个
int的shared_ptr - assert(spi); //在bool语
境中隐式转换为bool值 - *spi = 253; //使用解引用操作符*
- shared_ptr<string> sps(new string("smart")); //一
个string的shared_ptr - assert(sps->size() == 5); //使
用箭头操作符->
但shared_ptr的名字表明了它与scoped_ptr的主要不同:它是可以被安全共享的--shared_ptr是一个"全功能"的类,有着正常的拷贝、赋值语义,也可以进行shared_ptr间的比较,是"最智能"的智能指针。
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自动失去管理权;
operator=赋值操作符可以从另外一个shared_ptr或auto_ptr获得指针的管理权,其行为同构造函数;
shared_ptr(Y * p, D d)行为类似shared_ptr(Y * p),但使用参数d指定了析构时的定制删除器,而不是简单的delete。这部分将在3.4.5小节,75页详述。
shared_ptr的reset()函数的行为与scoped_ptr也不尽相同,它的作用是将引用计数减1,停止对指针的共享,除非引用计数为0,否则不会发生删除操作。带参数的reset()则类似相同形式的构造函数,原指针引用计数减1的同时改为管理另一个指针。
shared_ptr有两个专门的函数来检查引用计数。unique()在shared_ptr是指针的唯一所有者时返回true(这时shared_ptr的行为类似auto_ptr或scoped_ptr),use_count()返回当前指针的引用计数。要小心,use_count()应该仅仅用于测试或者调试,它不提供高效率的操作,而且有的时候可能是不可用的(极少数情形)。而unique()则是可靠的,任何时候都可用,而且比use_count()==1速度更快。
shared_ptr还支持比较运算,可以测试两个shared_ptr的相等或不相等,比较基于内部保存的指针,相当于a.get()==b.get()。shared_ptr还可以使用operator<比较大小,同样基于内部保存的指针,但不提供除operator<以外的比较操作符,这使得shared_ptr可以被用于标准关联容器(set和map):
- typedef shared_ptr<string> sp_t; //shared_ptr类型定义
- map<sp_t, int> m; //标准映射容器
- sp_t sp(new string("one")); //一个shared_ptr对象
- m[sp] = 111; //关联数组用法
在编写基于虚函数的多态代码时指针的类型转换很有用,比如把一个基类指针转型为一个子类指针或者反过来。但对于shared_ptr不能使用诸如static_cast<T*>(p.get())的形式,这将导致转型后的指针无法再被shared_ptr正确管理。为了支持这样的用法,shared_ptr提供了类似的转型函数static_pointer_cast<T>()、const_pointer_cast<T>()和dynamic_pointer_cast<T>(),它们与标准的转型操作符static_cast<T>、const_cast <T>和dynamic_cast<T>类似,但返回的是转型后的shared_ptr。
例如,下面的代码使用dynamic_pointer_cast把一个shared_ptr<std::exception>向下转型为一个shared_ptr<bad_exception>,然后又用static_pointer_cast重新转为shared_ptr<std::exception>:
- shared_ptr<std::exception> sp1(new bad_exception("error"));
- shared_ptr<bad_exception> sp2 = dynamic_
pointer_cast<bad_exception>(sp1); - shared_ptr<std::exception> sp3 = static_pointer_cast<std::
exception>(sp2); - assert(sp3 == sp1);
此外,shared_ptr还支持流输出操作符operator<<,输出内部的指针值,方便调试。