C++11智能指针中make_shared存在的必要性

作者: veaxen 分类: C/C++ 发布时间: 2018-11-03 02:31

前言

最近在看谷歌的开源项目sfntly,然后发现了这个项目中用的是智能指针与我之前学C++的时候接触的智能指针(shared_ptr)的实现方式不同,是两个不同的角度。所以为了更好的理解sfntly里智能指针的实现思想,我先对之前学习C++11标准库的智能指针做一个总结,由于之前没有记录,所以就写下本文,方便自己以后翻出了看。

要说到C++11智能指针的实现,我觉得最好的理解方式是搞清楚make_shared的存在。本文就从make_shared开始,大概说下智能指针的实现,以及为什么要存在make_shared。

引用计数原理

C++11中的shared_ptr的定义我们截取一部分大概是这样的:

template<class T>
class shared_ptr{
private:
    T *px;                          // 指向所引用对象的指针
    unsigned long* pn;      // 指向引用计数的指针
};

看了定义应该也容易明白shared_ptr的原理,就是用px来记录引用的对象的指针,使用pn来记录有多少个shared_ptr引用了相同对象(引用计数),当pn指向的引用计数为0时,delete px

shared_ptr和make_shared

C++11直接使用 shared_ptr<T>make_shared<T> 都可以创建智能指针。但是结合前面的简单说的原理,我们来讲下他们的区别。

shared_ptr

使用shared_ptr直接创建智能指针:

auto p = shared_ptr<int>(new int(100));

我们有下面的两个过程:
new int申请内存,并把指针传给shared_ptr中的px
– 在shared_ptr中,会另外申请一块内存,初始化引用计数为1,并把指针赋值给pn

这样把创建一个智能指针需要分两步申请内存,会存在下面两个问题:
– 当 new int 申请内存成功,但引用计数内存申请失败时,很可能造成内存泄漏。
– 内存分配是一个消耗性能的过程,分两次分配内存,意味着性能会下降

make_shared

为了解决直接使用shared_ptr创建智能指针带来的问题,C++11标准库引入了make_shared:

auto p = make_shared<int>(100);

make_shared只会申请一次内存,这块内存会大于int所占用的内存,多出的部分被用于智能指针引用计数。这样就避免了直接使用shared_ptr带来的问题。

不过make_shared并不是完美的

前面只说到强引用计数,其实智能指针还有弱引用计数。当强引用计数为0时,释放引用的对象内存,当弱引用计数为0时,释放引用计数所占用的内存

由于弱引用计数的存在,make_shared创建的智能指针引用的对象,可能无法得到及时的释放,只有当强/弱引用都为0时,才能释放make_shared申请的一整块内存

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.