shared_ptr
shared_ptr与scoped_ptr同样是用于管理new动态分配对象的智能指针,它们都重载了 *和->操作符,提供显示bool类型转换以判断指针的有效性,get()可以得到原始指针,并且没有提供指针算术操作,也不能管理new[ ] 产生的动态数组指针。
例:
shared_ptr<int> spi(new int);
//解引用
*spi = 222;
//一个string的shared_ptr
shared_ptr<string> sps(new string("smart"));
//获取大小
sps->size();
//危险,不能正确释放内存
shared_ptr<int> s(new int[10]);
特点:它是可以被安全共享的——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共享一个指针的管理权。
④operator=赋值操作符可以从另外一个shared_ptr获得指针的管理权,其行为同构造函数。
⑤reset()的作用是将引用计数减1,如果引用计数为0,则删除对象。
⑥use_count()返回当前的引用计数,仅仅用于测试或者调试,他不提供高效率操作,unique()则是可靠的,任何时候都可用。
⑦shared_ptr支持比较运算,a.get() == b.get()。它还可以使用operator < 比较大小,这使得它可以用于(set和map)。
⑧支持operator << 运算符,输出内部指针值,方便调试。
typedef shared_ptr<string> sp_t;
map<sp_t,int> m;
sp_t sp(new string("one"));
m[sp] = 111;
用法:
#include <iostream>
#include <string>
#include <boost/smart_ptr.hpp>
using namespace std;
using namespace boost;
int main()
{
//创建对象
boost::shared_ptr<int> sp(new int(10));
//判断是否是唯一
assert(sp.unique());
//第二个shared_ptr,调用拷贝构造
boost::shared_ptr<int> sp2 = sp;
//判断是否相等,并且引用计数为2
assert(sp == sp2 && sp.use_count() == 2);
//使用解引用操作符修改被指对象
*sp2 = 100;
//判断另外一个是否也同时被修改
assert(*sp == 100);
//停止shared_ptr的使用
sp.reset();
getchar();
return 0;
}
以下为shared_ptr应用于标准容器的用法:
#include <iostream>
#include <string>
#include <vector>
#include <boost/smart_ptr.hpp>
#include <boost/make_shared.hpp>
using namespace std;
using namespace boost;
int main()
{
typedef vector<boost::shared_ptr<int>> vs;
vs v(10);
//两种赋值方式
int i = 0;
//for (auto pos = v.begin(); pos != v.end(); ++pos)
//{
// //赋值
// (*pos) = boost::make_shared<int>(++i);
// cout << *(*pos) << ", ";
//}
for (auto &ptr : v)
{
ptr = boost::make_shared<int>(++i);
cout << *ptr << ", ";
}
cout << endl;
boost::shared_ptr<int> p = v[9];
*p = 100;
cout << *v[9] << endl;
getchar();
return 0;
}
定制删除器:
它拥有这个构造函数 shared_ptr(Y *p, D d)。
第一个参数与其他构造函数参数相同。第二个删除器参数d则告诉shared-ptr在析构时不是使用delete来操作指针p,而是用d来操作,即把 delete p 换成 d(p);
//假设有一组操作socket的函数,使用一个socket_t类
class socket_t {...};
//打开socket
socket_t *open()
{
cout<<"open socket"<<endl;
return new socket_t;
}
//关闭socket
socket_t *close()
{
cout<<"close socket"<<endl;
return new socket_t;
}
socket_t *s = open();
//传入删除器
shared_ptr<socket_t > p(s,close);
shared_ptr<void>
shared_ptr<void>能够存储void*类型的指针,而void*类型指针可以指向任意类型,因此shared_ptr<void>就像是一个泛型的指针容器,拥有容纳任意类型的能力,如果存储为void*型指针,为了在需要的时候正确使用,可以使用static_pointer_cast<T>等转型函数重新转为原来的指针,但它会使代码不够安全,建议不要这样使用。
别名构造函数
//一种比较特殊的构造函数
template<class Y>
shared_ptr(shared_ptr<Y> const &r,element_type *p)
它的作用是共享r的引用计数,但实际持有的却是另外一个可能毫无关系的指针p。而且并不负责p的自动销毁。一个使用例子
//一个pair的智能指针
auto p1 = make_shared<std::pair<int,int>>(0,1)
//别名构造
shared_ptr<int> p2(p1,&p1->second);
//原引用计数加1
assert(p1.use_count() == 2);
//两者引用计数相同
assert(p1.use_count() == p2.use_count());
//但指向的内容不同
assert((void *)p1.get() != (void*)p2.get());
//指向的是另外的指针
assert(&p1->second == p2.get())
shared_array
它的接口与功能与shared_ptr是相同的,主要区别:
①构造函数接受的指针是new[ ] 的结果
②提供operator[ ] 操作符重载
③没有 *、->操作符重载,因为它持有的不是一个普通指针
④析构函数使用delete[ ] 释放资源,而不是delete
用法:
#include <iostream>
#include <string>
#include <vector>
#include <boost/smart_ptr.hpp>
#include <boost/make_shared.hpp>
using namespace std;
using namespace boost;
int main()
{
int *p = new int[100];
shared_array<int> sa(p);
shared_array<int> sa2 = sa;
sa[0] = 10;
getchar();
return 0;
}
shared_array能力有限,多数情况下使用shared_ptr<std::vector>或者std::vector<shared_ptr>。