C++2.0 新特性—智能指针

C++2.0 新特性—智能指针不知道多少人诟病 C 传统指针使用时带来的内存管理 以及对内存对象拥有者不清晰的问题 如下面的代码 int fn

欢迎大家来到IT世界,在知识的湖畔探索吧!

C++2.0 新特性—智能指针

不知道多少人诟病C++传统指针使用时带来的内存管理,以及对内存对象拥有者不清晰的问题。如下面的代码:

int * fn(){

int * p = new int(0);

return p;

}

对于fn的调用者会感到困惑,我得到了一个指针,我应不应该释放其指向的内存空间呢?如果我不释放,会不会内存泄漏呢?如果我释放,万一它还有其它拥有者呢?原则上,应该是谁申请,谁释放,但是现实项目中往往不是总能做到。为此,智能指针被提出。智能指针通过引用计数的方式来管理内存,让使用者不再操心内存释放问题,一旦引用计数减为0,智能指针就会自动释放内存。

智能指针的不是从C++11开始的,早前c++98版本中就提供了auto_ptr智能指针,boost库也提供了,诸如scoped_ptr, shared_ptr, intrusive_ptr, weak_ptr等智能指针。到了c++11标准,则采用unique_ptr 替代了auto_ptr,同时引入了shared_ptr 和 weak_ptr(实际上C++ TR1就有了shared_ptr 和 weak_ptr,直到c++11才正式纳入标准)。下面我们来介绍一下从C++11标准开始引入的智能指针。

  1. unique_ptr

之所以使用unique_ptr来替代auto_ptr是因为auto_ptr使用不当可能会带来意想不到的结果。看下面的例子:

auto_ptr<int> p1(new int(0));

auto_ptr<int> p2 = p1; /*该语句执行完成后,p1将不再拥有其原来执行的内存区域。这个看似copy赋值,实际做的却是移动赋值操作,这会导致不期望的结果和bug。并且在c++标准容器中无法存储auto_ptr*/

因此c++11之后开始采用unique_ptr来替代auto_ptr。从名字上也能看出unique_ptr的特性。如下面的语句将会在编译时报错:

unique_ptr<int> p1(new int(0));

unique_ptr<int> p2 = p1; //编译时报错,因为unique_ptr不支持copy赋值构造。

unique_ptr无法复制给另外一个unique_ptr,也不能以传值的方式作为函数参数,也不可以使用在需要复制操作的c++标准算法库中的某些算法。下图展示了auto_ptr的用法。

(注: C++14之后可以使用make_unique 来创建一个unique_ptr,这种方式在下图中未展示。参考这里的代码:

auto p1 = make_unique<int>(100);// 创建unique_ptr初始化其指向内存存储的值为100

auto p2 = make_unique<int[]>(5);// 创建unique_ptr拥有5个元素的数组,在此无法初始化

for (int i = 0; i < 5; i++) { // 初始化p2的元素

p2[i] = i;

}

)

C++2.0 新特性---智能指针



欢迎大家来到IT世界,在知识的湖畔探索吧!

运行上图所示代码输出如下图:

C++2.0 新特性---智能指针

  1. shared_ptr

有了unique_ptr,我们很自然就会想到shared_ptr。C++11之后引入了shared_ptr来处理内存中一个对象有多个拥有者管理其生命周期的情况。shared_ptr支持复制,参数传值,和赋值操作。它通过内部引用计数来管理内存对象的生命周期,和unique_ptr一样,shared_ptr也可以看做一个管理着原始指针的容器。shared_ptr内部维护着一个引用计数,当该计数减为0时,shared_ptr就会删除其管理的原始指针指向的内存区。下图展示了shared_ptr的用法。下图中调用的shared_ptr的use_count函数可以得到其引用计数的值。

C++2.0 新特性---智能指针

shared_ptr不仅能管理对象,它也可以管理函数。比如下图所示的例子:

C++2.0 新特性---智能指针

运行上图代码会输出Hello.如下图所示。

C++2.0 新特性---智能指针

注意:使用一个shared_ptr拥有原始指针来构造另一个shared_ptr会导致未定义的行为。因此应该避免如下用法:

C++2.0 新特性---智能指针

上述代码运行可以得到:

C++2.0 新特性---智能指针

。所以,这是非常危险的,如果上图中sp1和sp2其中一个引用计数减为0,那么它就会释放管理的对象内存,而另一个shared_ptr还在管理一个已经被释放的对象,这将导致异常。

  1. weak_ptr

weak_ptr都是和shared_ptr配合使用,在使用weak_ptr时需要将它转成shared_ptr。weak_ptr的存在是用来解决某些情况下我们需要拥有一个对象,但是其引用计数却不能增加。比如shared_ptr的循环引用。下图中的例子说明了这种情况。

C++2.0 新特性---智能指针

运行上图中的代码可以得到:

C++2.0 新特性---智能指针

上图的例子说明发生了循环引用。这会导致spa和spb生命周期相互依赖而无法打破(类似死锁),因而spa和spb会驻留内存,造成内存泄漏。解决这个问题就是使用weak_ptr。下图展示了我们如何使用weak_ptr来解决上面的问题。

C++2.0 新特性---智能指针

运行上图的代码可以得到:

C++2.0 新特性---智能指针

从运行结果可以看到循环引用被打破了。那么我们如果要使用weak_ptr操作管理的对象该怎么办呢?假设上例中的spa的引用计数减为0了,然后spa就将管理的对象释放了。那么这时class B中的成员weak_ptr m_sp所拥有的对象也就被释放了。weak_ptr 提供了expired()函数, 该函数返回一个bool值可以判断weak_ptr所拥有的对象是否已经释放(过期了)。使用weak_ptr时需要用lock()函数将其转成shared_ptr来使用,如下图所示代码展示:

C++2.0 新特性---智能指针

本文介绍了C++2.0智能指针的基本概念和使用方法,希望对大家有所帮助。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/96783.html

(0)
上一篇 3小时前
下一篇 2小时前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信