智能指针 shared_ptr 解析

最近正在进行《Effective C++》的第二遍阅读,书里面多个条款涉及到了shared_ptr智能指针,介绍的太分散,学习起来麻烦,写篇blog整理一下。

LinJM   @HQU

shared_ptr是一个智能指针。在C++ 11颁布之前,它包含在TR1(Technical Report 1)当中,现在囊括在C++11的标准库中。

智能指针

智能指针(Smart pointers)是存储“指向动态分配(在堆上)的对象的指针”的对象。也就是说,智能指针其实是个对象。不过它的行为很像C++的内建指针,只是它们可以在适当的时候自动删除它们所指向的对象。智能指针在面对异常时有非常显著的作用,它们可以确保动态分配对象的完全析构。它们还可以用于跟踪多主人共享的动态分配对象。在概念上,智能指针可以看作拥有它所指向的对象,并因此在对象不再需要时负责将它删除。

如果对智能指针的概念还不是很清晰,再看下面的介绍:

A smart pointer is anabstract data type that simulates a pointer while providing additional features, such as automatic
memory management or bounds checking. These additional features are intended to reduce bugs caused by the misuse of pointers while retaining efficiency. Smart pointers typically keep track of the memory they point to. They may also be used to manage other
resources, such as network connections and file handles.     Misuse of pointers is a major source of bugs.Smart pointers prevent most situations of memory leaks by making the memory deallocation automatic.More generally, they make object destruction
automatic: the object controlled by a smart pointer is automatically destroyed (finalized and then deallocated) when the last (or only) owner of the object is destroyed, for example because the owner is a local variable, and execution leaves the variable‘s
scope. Smart pointers also eliminate dangling pointers by postponing destruction until the object is no longer in use.

shared_ptr

前面已经说了shared_ptr是个智能指针。类似于vector,智能指针也是模板。因此,当我们创建一个智能指针时,必须提供额外的信息——指针可以指向的类型。与vector一样,我们在尖括号内给出类型,之后是所定义的这种智能指针的名字:

shared_ptr<string> p1;     // shared_ptr,可以指向string
shared_ptr<list<int>> p2; // shared_ptr,可以指向int的list

默认初始化的智能指针中保存着一个空指针。

智能指针的使用方式与普通指针类似。解引用一个智能指针返回它指向的对象。如果在一个条件判断中使用智能指针,效果就是检测它是否为空:

//如果p1不为空,检查它是否指向一个空string
if (p1  && p1->empty())
    *p1 = "hi";   // 如果p1指向一个空string,解引用p1,将一个新值赋予string

下面列出shared_ptr支持的操作:

shared_ptr<T> p 空智能指针,可以指向类型为T的对象
p 将p用作一个条件判断,若p指向一个对象,则为true
*p 解引用p,获得它所指向的对象
p->mem 等价于(*p).mem
p.get()
返回p中保存的指针。要小心使用,若智能指针释放了其对象,返回指针所指向的对象也就消失了
swap(p,q)或p.swap(q) 交换p和q的指针
make_shared<T>(args) 返回一个shared_ptr,指向一个动态分配的类型为T的对象。使用args初始化此对象
shared_ptr<T> p(q)
p是shared_ptr q的拷贝;此操作会递增q中的计数器。q中的指针

必须能转化为T*

p=q
p和q都是shared_ptr,所保存的指针必须能相互转换。此操作会

递减p的引用计数,递增q的引用计数

p.unique() 若p.use_count()为1,返回true,否则返回false
p.use_count() 返回与p共享对象的智能指针数量:可能很慢,主要用于调试

例子:

//p3指向一个值为42的int的shared_ptr
shared_ptr<int> p3  = make_shared<int>(42);
//p4指向一个值为“99999999”的string
shared_ptr<string> p4 = make_shared<string>(10,‘9‘);

以对象管理资源

上面我们对shared_ptr进行了初步的介绍,不过它的优点我们还没开始阐述。shared_ptr的一个重大优点就是它实现了“以对象管理资源”这个资源管理思想。所谓资源就是,一旦使用了它,将来必须还给系统。在C++中最常使用的资源就是动态分配内存(如果你分配内存却从未归还过,那就会导致内存泄漏),主要通过一对运算符来完成:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化;delete,接受一个动态对象的指针,销毁该对象,并释放与之相关联的内存。

动态内存的使用很容易出现问题,因为确保在正确的时间释放内存是极其困难的。有时候我们会忘记释放内存,在这种情况下就会产生内存泄漏;有时在尚有指针引用内存的情况下我们就释放了它,在这种情况下就会产生非法引用内存的指针。

那么,为了更容易(同时更安全)地使用动态内存,我们需要使用智能指针类型来管理动态对象。在C++11之前,C++的标准库提供了auto_ptr来管理动态对象,而tr1中提供了shared_ptr。现在C++11新的标准库将tr1的内容包含进去,提供了两种智能指针来管理动态对象,这两种智能指针的区别在于管理底层指针的方式:shared_ptr允许多个指针指向同一个对象;unique_ptr则“独占”所指向的对象。标准库还定义了一个名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。

下面用一个例子来分析资源管理。

假设我们有一个class Investment,其中包含一个函数createInvestment()供应我们某特定的Investment对象:

// 返回指针,指向Investment继承体系内的动态分配对象。调用者有责任删除它。
// 这里为了简化,刻意不写参数
Investment * createInvestment();

一如注释所言,createInvestment的调用端使用了函数返回的对象后,有责任删除之。现在考虑有个f()函数履行这个责任:

void f()
{
	Investment * pInv = createInvestment();
	....
	delete pInv;
}

这看起来妥当,但在若干情况下f()可能无法删除它得自createInvestment的对象——或许因为“....”区域中一个过早的return语句或者异常返回,这样程序的控制流就绝不会触及delete语句,从而造成内存泄漏。当然啦,谨慎地编写程序可以防止这一类错误,但是你必须想想,代码可能会在时间渐渐过去后被修改。一旦软件开始维护,可能有人添加了return语句。因此,单纯地依赖“f()总是会执行其delete语句”是行不通的。

那我们该怎么办呢?很简单——以对象管理资源。把资源放进对象内,当控制流离开f( ),该对象的析构函数会自动释放那些资源。

void f()
{
	std::tr1::shared_ptr<Investment> pInv(createInvestment());
	.....
}

这个简单的例子示范了“以对象管理资源”的两个关键想法:

  • 获得资源后立刻放进管理对象内。以上代码中createInvestment返回的资源被当作其管理者shared_ptr的初值。实际上“以对象管理资源”的观念常被称为“资源取得时机便是初始化时机”,因为我们几乎总是在获得一笔资源后于同一语句内以它初始化某个管理对象。
  • 管理对象运用析构函数确保资源被释放。不论控制流如何离开区块,一旦对象被销毁其析构函数自然会被自动调用,于是资源被释放。

如果可以,我推荐你看看《C++ Primer》5th 的第12章,里面比较系统地介绍了shared_ptr的使用方法!!!!如果你想深入了解shared_ptr,那么Ref[6]值得学习。

Refs:

[1] Stanley B.Lippman. C++ Primer 5th 中文版.电子工业出版社, 2013.

[2] Scott Meyers. Effective C++中文版.电子工业出版社, 2011.

[3] Boost C++ libraries:Smart Pointers 智能指针.

[4] Boost C++ libraries:shared_ptr类模板

[5] John M. Dlugosz. Smart Pointers Overview

[6] std::tr1::shared_ptr源码赏析

[7] Yonat Sharon. Smart Pointers - What, Why, Which?

本文地址:http://blog.csdn.net/linj_m/article/details/25045403

更多相关资源 请关注博客:LinJM-机器视觉 微博:林建民-机器视觉

智能指针 shared_ptr 解析

时间: 2024-11-06 19:36:37

智能指针 shared_ptr 解析的相关文章

C++智能指针 shared_ptr

C++智能指针 shared_ptr shared_ptr 是一个标准的共享所有权的智能指针, 允许多个指针指向同一个对象. 定义在 memory 文件中(非memory.h), 命名空间为 std. shared_ptr 是为了解决 auto_ptr 在对象所有权上的局限性(auto_ptr 是独占的), 在使用引用计数的机制上提供了可以共享所有权的智能指针, 当然这需要额外的开销: (1) shared_ptr 对象除了包括一个所拥有对象的指针外, 还必须包括一个引用计数代理对象的指针. (

C/C++之智能指针shared_ptr

1.定义 shared_ptr的作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象.这便是所谓的引用计数(reference counting).一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除.这在非环形数据结构中防止资源泄露很有帮助. auto_ptr由于它的破坏性复制语义,无法满足标准容器对元素的要求,因而不能放在标准容器中:如果我们希望当容器析构时能自动把它容纳的指针元素所指的对象删除时,通常采用一些间接的方式来实现,显得比较繁琐

【C++】智能指针shared_ptr 定位删除器(仿函数)

智能指针shared_ptr 用引用计数实现看起来不错,但却存在问题. 1.引用计数更新存在着线程安全: 2.循环引用--使用一个弱引用智能指针(weak_ptr)来打破循环引用(weak_ptr不增加引用计数) 3.定置删除器和空间分配器 比如打开一个文件的关闭,用malloc开辟出来的空间,用引用计数实现会出现问题. 对改变引用计数时加锁可以解决引用计数更新存在着线程安全. 循环引用问题 #include<iostream> using namespace std; #include<

c/c++ 智能指针 shared_ptr 使用

智能指针 shared_ptr 使用 上一篇智能指针是啥玩意,介绍了什么是智能指针. 这一篇简单说说如何使用智能指针. 一,智能指针分3类:今天只唠唠shared_ptr shared_ptr unique_ptr weak_ptr 二,下表是shared_ptr和unique_ptr都支持的操作 操作 功能描述 shared_ptr<T> sp 空智能指针,可以指向类型为T的对象 unique_ptr<T> up 空智能指针,可以指向类型为T的对象 p 将p用作一个条件判断,如果

C++智能指针简单解析

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

智能指针——shared_ptr

boost::scoped_ptr虽然简单易用,但它不能共享所有权的特性却大大限制了其使用范围,而boost::shared_ptr可以解决这一局限.顾名思义,boost::shared_ptr是可以共享所有权的智能指针 boost::shared_ptr的管理机制其实并不复杂,就是对所管理的对象进行了引用计数,当新增一个boost::shared_ptr对该对象进行管理时,就将该对象的引用计数加一:减少一个boost::shared_ptr对该对象进行管理时,就将该对象的引用计数减一,如果该对

Boost库中的智能指针 shared_ptr智能指针

shared_ptr智能指针的意思即:boost::shared_ptr是可以智能的管理动态分配的内存资源,几个智能指针可以同时共享一个动态分配的内存的所有权. 下面我们通过一个例子来学习一下它的用法: 注 :使用shared_ptr智能指针,要加入#include <boost/shared_ptr.hpp>头文件 class example { public: ~example() { std::cout <<"It's over\n"; } void do

Boost智能指针——shared_ptr

转: http://www.cnblogs.com/TianFang/archive/2008/09/19/1294521.html boost::scoped_ptr虽然简单易用,但它不能共享所有权的特性却大大限制了其使用范围,而boost::shared_ptr可以解决这一局限.顾名思义,boost::shared_ptr是可以共享所有权的智能指针,首先让我们通过一个例子看看它的基本用法: #include <string> #include <iostream> #inclu

C++智能指针shared_ptr

shared_ptr 这里有一个你在标准库中找不到的—引用数智能指针.大部分人都应当有过使用智能指针的经历,并且已经有很多关于引用数的文章.最重要的一个细节是引用数是如何被执行的—插入,意思是说你将引用计数的功能添加给类,或者是非插入,意思是说你不这样做.Boost shared_ptr是非插入类型的,这个实现使用一个从堆中分配来的引用计数器.关于提供参数化策略使得对任何情况都极为适合的讨论很多了,但是最终讨论的结果是决定反对聚焦于可用性.可是不要指望讨论的结果能够结束. shared_ptr完