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

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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-06-06

C++11新特性之智能指针(shared_ptr/unique_ptr/weak_ptr)

shared_ptr基本用法 shared_ptr采用引用计数的方式管理所指向的对象.当有一个新的shared_ptr指向同一个对象时(复制shared_ptr等),引用计数加1.当shared_ptr离开作用域时,引用计数减1.当引用计数为0时,释放所管理的内存. 这样做的好处在于解放了程序员手动释放内存的压力.之前,为了处理程序中的异常情况,往往需要将指针手动封装到类中,通过析构函数来释放动态分配的内存:现在这一过程就可以交给shared_ptr去做了. 一般我们使用make_shared来

c++11&14-智能指针要点汇总

学c++的人都知道,在c++里面有一个痛点,就是动态内存的管理,就我所经历的一些问题来看,很多莫名其妙的问题,最后都发现是内存管理不当引起的. 但像java等其他一些语言则不会有这样的问题,为什么呢,因为它们有很好的处理内存的方法,比如java的垃圾回收机制,现在,我们c++终于也有了智能指针. 1. 什么是智能指针 简单地说,智能指针是用对象去管理一个资源指针,同时用一个计数器计算引用当前指针对象的个数,当管理指针的对象增加或减少时,计数器也相应加1或减1,当最后一个指针管理对象销毁时,计数器

C++11智能指针之weak_ptr详解

如题,我们今天要讲的是 C++11 引入的三种智能指针中的:weak_ptr. 在学习 weak_ptr 之前最好对 shared_ptr 有所了解.如果你还不知道 shared_ptr 是何物,可以看看另一篇文章: [C++11新特性] C++11智能指针之shared_ptr 1.为什么需要weak_ptr? 在正式介绍weak_ptr之前,我们先来回忆一下shared_ptr的一些知识. 我们知道shared_ptr是采用引用计数的智能指针,多个shared_ptr实例可以指向同一个动态对

C++11智能指针中的 unique_ptr实例详解

在前面一篇文章中,我们了解了 C++11 中引入的智能指针之一 shared_ptr 和 weak_ptr ,今天,我们来介绍一下另一种智能指针 unique_ptr . 往期文章参考: [C++11新特性] C++11 智能指针之shared_ptr [C++11新特性] C++11智能指针之weak_ptr unique_ptr介绍 unique是独特的.唯一的意思,故名思议,unique_ptr可以"独占"地拥有它所指向的对象,它提供一种严格意义上的所有权. 这一点和我们前面介绍

c++11&14-多线程要点汇总

在C++11以前,C++的多线程编程均需依赖系统或第三方接口实现,一定程度上影响了代码的移植性.C++11中,引入了boost库中的多线程部分内容,形成C++标准,形成标准后的boost多线程编程部分接口基本没有变化,这样方便了以前使用boost接口开发的使用者切换使用C++标准接口,很容易把boost接口升级为C++标准接口. 我们通过如下几部分介绍C++11多线程方面的接口及使用方法. 1. std::thread std::thread为C++11的线程类,使用方法和boost接口一样,非

C++11的新特性简单汇总介绍 (二)

1. 范围for语句 C++11 引入了一种更为简单的for语句,这种for语句可以很方便的遍历容器或其他序列的所有元素 vector<int> vec = {1,2,3,4,5,6}; for(int x: vec) { cout<<x<<endl; } 2. 尾置返回类型 要想引入尾置类型,我们还得从复杂的类型声明说起.如果我们需要定义一个含有10个int元素的数组,一般是这样的: int arr[10] = {0}; 如果要定义指向这个数组的指针呢: 复制代码 代

C++智能指针读书笔记

最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的问题,比如你知道哪些智能指针?shared_ptr的设计原理是什么?如果让你自己设计一个智能指针,你如何完成?等等--.而且在看开源的C++项目时,也能随处看到智能指针的影子.这说明智能指针不仅是面试官爱问的题材,更是非常有实用价值. C++通过一对运算符 new 和 delete 进行动态内存管理,new在动态内存中

C++智能指针实例详解

本文通过实例详细阐述了C++关于智能指针的概念及用法,有助于读者加深对智能指针的理解.详情如下: 一.简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete.程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见. 用智能指针便可以有效缓解这类问题,本文主要讲解参见的智能指针的用法.包括:std::auto_ptr.boost::scoped_ptr.boost::shared_p

C++中的auto_ptr智能指针的作用及使用方法详解

智能指针(auto_ptr) 这个名字听起来很酷是不是?其实auto_ptr 只是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势,但也有其局限.本文总结的8个问题足以涵盖auto_ptr的大部分内容.  auto_ptr是什么? auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者.当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥

C++ 中boost::share_ptr智能指针的使用方法

C++ 中boost::share_ptr智能指针的使用方法 最近项目中使用boost库的智能指针,感觉智能指针还是蛮强大的,在此贴出自己学习过程中编写的测试代码,以供其他想了解boost智能指针的朋友参考,有讲得不正确之处欢迎指出讨论.当然,使用boost智能指针首先要编译boost库,具体方法可以网上查询,在此不再赘述. 智能指针能够使C++的开发简单化,主要是它能够自动管理内存的释放,而且能够做更多的事情,即使用智能指针,则可以再代码中new了之后不用delete,智能指针自己会帮助你管理