概解:
本文是自己在学习boost库完全开发的时候顺手做的笔记,摘出其中自认为是比较重要的部分以作整理并写成博文,分享出来,很是奇怪csdn代码块那块有颜色代码,不知道怎么去掉、、、因为没咋仔细研究、、、所以这编将就先弄着,等有时间再仔细研究一番这个:
shared_ptr非常有价值、非常重要、非常有用!
shared_ptr是一个最像指针的"智能指针",是boost::smart_ptr库中最有价值、最重要的组成部分,也是最有用的,Boost库中许多组件--甚至还包括其他一些领域的智能指针都使用了shared_ptr。
shared_ptr与scoped_ptr一样包装了new操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针,可以被自由地拷贝和赋值,在任意的地方共享它。当没有代码使用(引用计数为0)它才删除呗包装的动态分配的对象,shared_ptr也可以被安全的放到标准容器中,并弥补了auto_ptr因为转移语义而不能把指针作为STL容器元素的缺陷;
类摘要:
template<class T>
class shared_ptr
{
public:
typdef T elment_type;
shared_ptr();
template<class Y> explicit shared_ptr(Y *p);
template<class Y,class D> shared_ptr(Y *p,D d);
~shared_ptr();
shared_ptr(shared_ptr const &r);
template<class Y>explicit shared_ptr(std::auto_ptr<Y> &r);
shared_ptr& operator=(shared_ptr const &r);
template<class Y>shared_ptr &operator=(shared_ptr<Y> const &r);
template<class Y>shared_ptr &operator=(std::auto_ptr<Y> &r);
void reset();
template<class Y>void reset(Y *p);
template<class Y,class D>void reset(Y *p,D d);
T &operator*() const;
T *operator->() const;
T *get() const;
bool unique() const;
long use_count() const;
operator unspecified-bool-type() const;
void swap(shared_ptr &b);
};
shared_ptr的定义:
shared_ptr<int> psi(new int);
assert(spi);
*spi = 235;
shared_ptr<string> sps(new string("smart"));
assert(sps->size() == 5);
shared_ptr有多种形式的构造 函数,应用于各种可能的情形:
a、无参的shared_ptr() 创建一个持有空指针的shared_ptr;
b、shared_ptr(Y *p)获得指向类型T的指针p的管理权,同时引用计数置为1,这个构造函数要求Y类型必须能够转换为T类型;
c、shared_ptr(shared_ptr const &r)从另外一个shared_ptr获得指针的管理权,同时引用计数加1,结果是两个shared_ptr共享一个指针的管理权;
d、shared_ptr(std::auto_ptr<Y> &r)从一个auto_ptr获得指针的管理权,引用计数置为1,同时auto_ptr自动失去管理权;
e、operator=赋值操作符可以从另外一个shared_ptr或auto_ptr获得指针的管理权,其行为同构造函数;
f、shared_ptr(Y *p,D d)行为类似shared_ptr(Y *p),但使用参数d指定了析构时的定制删除器,而不是简单的delete。
特点:
a、sharedn_ptr的reset()函数行为与scoped_ptr也不尽相同,它的作用是将引用计数减1,停止对指针共享,除非引用计数为0,否则不会发生删除操作,带参的reset()类似同形式的构造函数,原指针引用计数减1的同时改为管理另一个指针;
b、shared_ptr有两个专门的函数来检查引用计数,unique()在shared_ptr是指针的唯一所有者时返回true(这时shared_ptr的行为类似于auto_ptr或者socped_ptr),use_count()返回当前只针对额引用计数,注意!use_count()应该仅仅用于测试或者调试环境,它不提供高效率的操作,而且有时候可能是不可用的(极少数情形),而unique()则是可靠的,任何时候都可以用,而且use_count() == 1速度更快;
c、shared_ptr还支持比较运算,可以测试两个shared_ptr的相等或者不想等,比较基于内部保存的指针,相当于a.get() == b.get().shared_ptr还可以使用operatoe<比较大小,同样基于内部保存的指针,但不提供除operator<以外的比较操作符,这使得shared_ptr可以被用于标准关联容器(set And 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的类型转换主要体现在类的多态。如将一个基类以及子类的指针进行互转,shared_ptr不能直接使用标准库中提供的类型转换函数,诸如:static_cast<T *>(p.get())这种用法,这将导致指针管理处于不可控状态,但是shared_ptr有一套自己的类型转换接口:
a、static_pointer_cast<T>()
b、const_pointer_cast<T>()
c、dynamic_pointer_cast<T>()
上面三个接口与标准库提供的类型转换类似,但返回的是转型后的shared_ptr;如下示例,将一个指针进行类型转换后再转换回去的操作:
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<<,输出内部的指针值,方便调试;
shared_ptr的使用:
shared_ptr100%涵盖了new的基本功能,且使用完毕后不用想new操作符那样进行手动delete,而且shared_ptr也是线程安全的,可以同时在多个线程内进行读取操作,其它访问均为未定义的操作,示例如下:
样例一:
shared_ptr<int> sp(new int(10)); //指向int的shared_ptr
assert(sp.unique()); //shared_ptr是指针的唯一持有者
shared_ptr<int> sp2 = sp; //第二个指针,拷贝构造且计数加1
assert(sp == sp2 && sp.use_count() == 2);//两个相等,指向同一个对象,引用计数为2
*sp2 = 100; //使用解引用操作符修改被指对象
assert(*sp == 100); //另一个对象shared_ptr的值也同时被修改
sp.reset(); //停止shared_ptr的使用
assert(!sp); //sp不再持有任何指针,此时为null
样例二:
class shared
{
private:
shared_ptr<int> p;
public:
shared(shared_ptr<int> p_):p(p_){}
void print()
{
cout << "count: " << p.use_count() << "V = " << *p << endl;
}
};
void print_func(shared_ptr<int> p)
{
cout << "count: " << p.use_count() << "value: " << *p << endl;
}
int main()
{
shared_ptr<int> p(new int(100));
shared s1(p), s2(p);
s1.print();
s2.print();
*p = 20;
print_func(p);
s1.print();
}
上例详解:
样例二定义了一个类以及一个函数,需要注意的是,两者都是直接拷贝的方式传递的参数,而不是引用,这样的话在创建shared_ptr以及实例化shared类的时候count此时的计数为3,之后又再次往print_func传递了参数此时count值为4,因为shared_ptr在退出的时候会自动调用析构所以在最后那块的打印count为3;