C++11 智能指针之shared_ptr代码详解

 更新时间:2020年6月8日 13:43  点击:1604

C++中的智能指针首先出现在“准”标准库boost中。

随着使用的人越来越多,为了让开发人员更方便、更安全的使用动态内存,C++11也引入了智能指针来管理动态对象。

在新标准中,主要提供了shared_ptr、unique_ptr、weak_ptr三种不同类型的智能指针。

接下来的几篇文章,我们就来总结一下这些智能指针的使用。

今天,我们先来看看shared_ptr智能指针。

shared_ptr 智能指针

shared_ptr是一个引用计数智能指针,用于共享对象的所有权也就是说它允许多个指针指向同一个对象。这一点与原始指针一致。

先来一段简单的代码,看看shared_ptr的简单使用:

#include <iostream>
#include <memory>
using namespace std;

class Example
{
public:
 Example() : e(1) { cout << "Example Constructor..." << endl; }
 ~Example() { cout << "Example Destructor..." << endl; }

 int e;
};

int main() {

 shared_ptr<Example> pInt(new Example());
 cout << (*pInt).e << endl;
 cout << "pInt引用计数: " << pInt.use_count() << endl;

 shared_ptr<Example> pInt2 = pInt;
 cout << "pInt引用计数: " << pInt.use_count() << endl;
 cout << "pInt2引用计数: " << pInt2.use_count() << endl;
}

程序输出如下:

Example Constructor...
pInt: 1
pInt引用计数: 1
pInt引用计数: 2
pInt2引用计数: 2
Example Destructor...

从上面这段代码中,我们对shared_ptr指针有了一些直观的了解。

一方面,跟STL中大多数容器类型一样,shared_ptr也是模板类,因此在创建shared_ptr时需要指定其指向的类型。

另一方面,正如其名一样,shared_ptr指针允许让多个该类型的指针共享同一堆分配对象。

同时shared_ptr使用经典的“引用计数”方法来管理对象资源,每个shared_ptr对象关联一个共享的引用计数。

对于shared_ptr在拷贝和赋值时的行为,《C++Primer第五版》中有详细的描述:

每个shared_ptr都有一个关联的计数值,通常称为引用计数。无论何时我们拷贝一个shared_ptr,计数器都会递增。

例如,当用一个shared_ptr初始化另一个shred_ptr,或将它当做参数传递给一个函数以及作为函数的返回值时,它 所关联的计数器就会递增。

当我们给shared_ptr赋予一个新值或是shared_ptr被销毁(例如一个局部的 shared_ptr离开其作用域)时,计数器就会递减。

一旦一个shared_ptr的计数器变为0,它就会自动释放自己所管理 的对象。

对比我们上面的代码可以看到:当我们将一个指向Example对象的指针交给pInt管理后,其关联的引用计数为1。

接下来,我们用pInt初始化pInt2,两者关联的引用计数值增加为2。随后,函数结束,pInt和PInt2相继离开函数作用于,相应的引用计数值分别自减1最后变为0,于是Example对象被自动释放(调用其析构函数)。

接下来,我们完整地介绍一下shared_ptr的常见用法:

1、创建shared_ptr实例

最安全和高效的方法是调用make_shared库函数,该函数会在堆中分配一个对象并初始化,最后返回指向此对象的share_ptr实例。

如果你不想使用make_ptr,也可以先明确new出一个对象,然后把其原始指针传递给share_ptr的构造函数。

示例如下:

int main() {

 // 传递给make_shared函数的参数必须和shared_ptr所指向类型的某个构造函数相匹配
 shared_ptr<string> pStr = make_shared<string>(10, 'a');
 cout << *pStr << endl; // aaaaaaaaaa

 int *p = new int(5);
 shared_ptr<int> pInt(p);
 cout << *pInt << endl; // 5
}

2、访问所指对象

shared_ptr的使用方式与普通指针的使用方式类似,既可以使用解引用操作符*获得原始对象进而访问其各个成员,也可以使用指针访问符->来访问原始对象的各个成员。

3、拷贝和赋值操作

我们可以用一个shared_ptr对象来初始化另一个share_ptr实例,该操作会增加其引用计数值。

例如:

int main() {
 shared_ptr<string> pStr = make_shared<string>(10, 'a');
 cout << pStr.use_count() << endl; // 1

 shared_ptr<string> pStr2(pStr);
 cout << pStr.use_count() << endl; // 2
 cout << pStr2.use_count() << endl; // 2
}

如果shared_ptr实例p和另一个shared_ptr实例q所指向的类型相同或者可以相互转换,我们还可以进行诸如p = q这样赋值操作。

该操作会递减p的引用计数值,递增q的引用计数值。

例如:

class Example
{
public:
 Example(string n) : name(n) { cout << n << " constructor..." << endl; }
 ~Example() { cout << name << " destructor..." << endl; }

 string name;
};

int main() {

 shared_ptr<Example> pStr = make_shared<Example>("a object");
 shared_ptr<Example> pStr2 = make_shared<Example>("b object");
 cout << pStr.use_count() << endl;
 cout << pStr2.use_count() << endl;

 pStr = pStr2; // 此后pStr和pStr指向相同对象
 cout << pStr->name << endl;
 cout << pStr2->name << endl;
}

输出如下:

a object constructor...
b object constructor...
1
1
a object destructor...
b object
b object
b object destructor...

4、检查引用计数

shared_ptr提供了两个函数来检查其共享的引用计数值,分别是unique()和use_count()。

在前面,我们已经多次使用过use_count()函数,该函数返回当前指针的引用计数值。值得注意的是use_count()函数可能效率很低,应该只把它用于测试或调试。

unique()函数用来测试该shared_ptr是否是原始指针唯一拥有者,也就是use_count()的返回值为1时返回true,否则返回false。

示例:

int main() {
 shared_ptr<string> pStr = make_shared<string>(10, 'a');
 cout << pStr.unique() << endl; // true

 shared_ptr<string> pStr2(pStr);
 cout << pStr2.unique() << endl; // false;
}

总结

到此这篇关于C++11 智能指针之shared_ptr代码详解的文章就介绍到这了,更多相关 C++11 shared_ptr内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • 解决 VSCode 编写 C++11 代码报红问题分析

    今天在写 C++ 代码的时候用上 C++11 的特性,然后发现 VSCode 虽然可以编译通过,但是会在相应位置报红,这是怎么回事呢?下面小编给大家带来了解决方法,一起看看吧...2021-09-27
  • 深入学习C++智能指针之shared_ptr与右值引用的方法

    智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存,今天通过本文给大家分享C++智能指针之shared_ptr与右值引用的方法,需要的朋友跟随小编一起看看吧...2021-07-13
  • c++11中regex正则表达式示例简述

    这篇文章主要给大家介绍了关于c++11中regex正则表达式的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用c++11具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-04-25
  • C++智能指针shared_ptr分析

    这篇文章主要介绍了C++智能指针shared_ptr分析的相关资料,需要的朋友可以参考下...2020-04-25
  • C语言智能指针之weak_ptr浅析

    这篇文章主要介绍了 C++11智能指针之weak_ptr详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-10-18
  • C++11中的原子量和内存序详解

    这篇文章主要给大家介绍了关于C++11中原子量和内存序的相关资料,文中通过示例代码介绍地方非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C++11 std::shared_ptr总结与使用示例代码详解

    这篇文章主要介绍了C++11 std::shared_ptr总结与使用,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-06-08
  • 一篇文章带你了解C++智能指针详解

    这篇文章主要介绍了c++ 智能指针基础的相关资料,帮助大家更好的理解和学习使用c++,感兴趣的朋友可以了解下,希望能给你带来帮助...2021-08-13
  • C++11中的default函数使用

    这篇文章主要介绍了C++11中的default函数使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-01
  • C++中auto_ptr智能指针的用法详解

    这篇文章主要介绍了C++中auto_ptr智能指针的用法详解的相关资料,需要的朋友可以参考下...2020-04-25
  • C++11各种锁的具体使用

    本文主要介绍了C++11各种锁的具体使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-08-10
  • C++11中std::declval的实现机制浅析

    这篇文章主要给大家介绍了关于C++11中std::declval实现机制的相关资料,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。...2020-04-25
  • C++11 简单实现线程池的方法

    这篇文章主要介绍了C++11 简单实现线程池的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-27
  • C++智能指针读书笔记

    本篇随笔仅作为个人学习《C++ Primer》智能指针一节后的部分小结,抄书严重,伴随个人理解。主要介绍shared_ptr、make_shared、weak_ptr的用法和联系...2020-04-25
  • 浅析Boost智能指针:scoped_ptr shared_ptr weak_ptr

    虽然通过弱引用指针可以有效的解除循环引用,但这种方式必须在程序员能预见会出现循环引用的情况下才能使用,也可以是说这个仅仅是一种编译期的解决方案,如果程序在运行过程中出现了循环引用,还是会造成内存泄漏的...2020-04-25
  • C++11特性小结之decltype、类内初始化、列表初始化返回值

    这篇文章主要介绍了C++11特性小结之decltype、类内初始化、列表初始化返回值,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-05-25
  • 浅析C++11中的右值引用、转移语义和完美转发

    对于c++11来说移动语义是一个重要的概念,一直以来我对这个概念都似懂非懂。最近翻翻资料感觉突然开窍,因此顺便记录下C++11中的右值引用、转移语义和完美转发,方便大家查阅参考。...2020-04-25
  • C++11中lambda、std::function和std:bind详解

    大家都知道C++11中增加了许多的新特性,下面在这篇文中我们就来聊一下lambda表达式,闭包,std::function以及std::bind。文中介绍的很详细,相信对大家具有一定的参考价值,有需要的朋友们下面来一起看看吧。...2020-04-25
  • C++11新特性之auto的使用

    熟悉脚本语言的人都知道,很多脚本语言都引入了“类型自动推断”技术:比如Python,可以直接声明变量,在运行时进行类型检查。随着C++11标准的发布,C++语言也引入了类型自动推断的功能。这篇文章主要介绍了C++11新特性之auto的使用,有需要的朋友们可以参考借鉴。...2020-04-25
  • C++11返回类型后置语法的使用示例

    本篇文章主要介绍了C++11返回类型后置语法的使用示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25