Boost库基础-智能指针(shared_ptr)

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>。

猜你喜欢

转载自blog.csdn.net/wzz953200463/article/details/105056283