您的位置:首页 > 编程语言 > C语言/C++

c++11之shared_ptr智能指针使用

2018-03-05 14:54 736 查看
shared_ptr类模板介绍

share_ptr是智能指针模板,创建智能指针对象时,需要指定可以指向的类型:

shared_ptr< string >       p1;//指向string类型
shared_ptr< list<string> > p2;//指向string类型的list


默认的智能指针对象中保存着空指针,智能指针的操作和普通指针一样,支持解引用(*)和成员操作符(->),也可以用智能指针对象来判空操作。

shared_ptr< string >       sp1;//指向string类型
if(!sp1)
{
cout << "it is empty\n";
sp1 = make_shared<string>("hello world");
}

cout << *sp1 <<endl;
//it is empty
//hello world


相对于unique_ptr独有操作:

make_shared<T>(args)
//返回一个shared_ptr,指向动态分配的类型为T的对象,使用args初始化此对象

shared_ptr<T>p(q)
//p是shared_ptr q的拷贝

p = q;
//p和q都是shared_ptr,所保存的指针必须能相互转换,p原来所指的计数器减一,q原来所指的计算器加一。

p.use_count()
//返回与p共享对象的智能指针数量,可能很慢,主要用于调试。


shared_ptr对象初始方式

最安全的分配和使用动态内存的方式是调用make_shared的标准库,例如:

//指向一个int类型值为42的share_ptr;
shared_ptr<int>     sp1 = make_shared<int>(10);
//指向一个string类型的shared_ptr
shared_ptr<string>  sp2 = make_shared<string>("hello world");


也可以中new方式进行初始化:

//指向一个int类型值为42的share_ptr;
shared_ptr<int>     sp1(new int(10));
//指向一个string类型的shared_ptr
shared_ptr<string>  sp2(new string("hello world"));


在c++11中,我们可以用auto定义对象来保存make_shared的返回结果,这种方式比较简单,例如:

//指向一个int类型值为42的share_ptr;
auto sp1 = make_shared<int>(10);
//指向一个string类型的shared_ptr
auto sp2 = make_shared<string>("hello world");


自动销毁所管理的对象

share_ptr智能指针是允许多个share_ptr同时指向某个对象,具有共享的特性;它们通过引用计数器方式,实现对对象的管理;

当一个shared_ptr对象被销毁时,其析构函数会递减它所指向的对象的引用计数器。当引用计数器变为 零时,shared_ptr的析构函数就会销毁对象,并释放它占用的内存。

int main()
{
auto p1 = make_shared<int>(10);

//wp1是p1所指向对象的观察器
weak_ptr<int> wp1 = p1;
cout <<"before  " <<"wp1 point to obj ref num: " << wp1.use_count() << " " <<endl;

auto p2 =  make_shared<int>(100);
//wp2是p2所指向对象的观察器
weak_ptr<int> wp2 = p2;
cout <<"before  " <<"wp2 point to obj ref num: " << wp2.use_count() << " " <<endl;

//复制操作
p1 = p2;//给p1赋值,令他指向另外一个地址
//递增p2原来指向对象的计数器
//递减p1原来指向对象的计数器
//p1原来指向对象的计数器变为零,对象内存自动释放

cout <<"after  " << "wp2 point to obj ref num: " << wp2.use_count() << " " <<endl;
cout <<"after  " << "wp1 point to obj ref num: " << wp1.use_count() << " " <<endl;

return 0;
}


运行结果:

before  wp1 point to obj ref num: 1
before  wp2 point to obj ref num: 1
after  wp2 point to obj ref num: 2
after  wp1 point to obj ref num: 0


NOTE:

一旦引用计数器不为零,其所指向的内存空间都不会被释放,造成内存泄漏;因此shared_ptr无用武之地后,保证智能指针对象及时析构,变得非常重要,否则浪费内存。

定制删除器

默认情况下,shared_ptr假定它们指向的是动态内存。因此,一个share_ptr被销毁时,它默认对他管理的指针进行delete操作。为了能够用shared_ptr来管理非动态内存的指针时,我们需要特殊定制一个函数来替代delete操作。这个函数就叫做删除器(deleter)。

下面展示删除器的使用,其入参是T*类型,代码如下:

shared_ptr<int> sp(new int(10), [](int *p){
cout << "call own deleter function\t ";
cout << "value: " << *p << endl;
delete p;

//指向的对象析构,调用删除器,lambda表达
sp.reset();


运行结果:

call own deleter function    value: 10


智能指针陷阱

智能指针可以提供对动态分配的内存进行安全而又方便的管理,当这是建立在正确使用的前提下。为了正确使用智能指针,我们必须坚持一个基本规范:

不用使用相同的内置指针初始化或者reset多个智能指针

不delete get()返回的指针

不使用get()初始化或者reset另外一个指针

如果你使用get()返回的指针,记住当最后一个对应的智能指针销毁后,你的指针就变为无效了

如果你使用的指针指针管理的指针不是new分配的内存,记住传递给它一个删除器。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息