动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
电脑书籍下载:程序设计书籍 | 数据库教程书籍 | 平面与多媒体书籍 | 网络通讯书籍 | 系统管理书籍 | 网络安全书籍 | 认证考试书籍
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > C/C++教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ C/C++教程 ]的信息



本月文章推荐
.C语言高效编程的的四招技巧.
.C程序设计语言概论.
.用GDI+实现半透明渐变的特效窗口.
.Visual C++设计UDP协议通讯示例.
.C语言图形编程(二、图形显示).
.Visual C++ 入门精解-第三部分.
.C语言初学者入门讲座 第二讲 数据.
.C++中的 static 关键字.
.QQ用户小心了! C语言实现QQ密码大.
.C语言入门之分支结构(1).
.点阵字模工具编程辅助效果示例.
.多变的立方体.
.C++ Builder 初学问与答(三).
.罗云彬VxD教程--DeviceIoControl.
.深入浅出Win32多线程程序设计之基.
.从源程序看原理:突破防火墙入侵内.
.Winsock技术在远程监控中的应用.
.经典c程序100例==71--80.
.String类的一些赋值语句.
.控制C++的内存分配.

C++箴言:资源管理类的拷贝行为

发表日期:2008-3-8 |



  在上一篇文章中介绍了作为资源治理类支柱的 Resource Acquisition Is Initialization (RAII) 原则,并描述了 auto_ptr 和 tr1::shared_ptr 在基于堆的资源上运用这一原则的表现。并非所有的资源都是基于堆的,然而,对于这样的资源,像 auto_ptr 和 tr1::shared_ptr 这样的智能指针通常就不像 resource handlers(资源治理者)那样合适。在这种情况下,有时,你可能要根据你自己的需要去创建你自己的资源治理类。

  例如,假设你使用 C API 提供的 lock 和 unlock 函数去操纵 Mutex 类型的互斥体对象:

  

  void lock(Mutex *pm); // lock mutex pointed to by pm

  

  void unlock(Mutex *pm); // unlock the mutex

  为了确保你从不会忘记解锁一个被你加了锁的 Mutex,你希望创建一个类来治理锁。RAII 原则规定了这样一个类的基本结构,通过构造函数获取资源并通过析构函数释放它:

  

  class Lock {

   public:

    eXPlicit Lock(Mutex *pm)

    : mutexPtr(pm)

    { lock(mutexPtr); } // acquire resource

   

    ~Lock() { unlock(mutexPtr); } // release resource

  

   private:

    Mutex *mutexPtr;

  };

  客户按照 RAII 风格的惯例来使用 Lock:

  

  Mutex m; // define the mutex you need to use

  ...

  { // create block to define critical section

   Lock ml(&m); // lock the mutex

   ... // perform critical section operations

  

  } // automatically unlock mutex at end

  // of block

  这没什么问题,但是假如一个 Lock 对象被拷贝应该发生什么?
  Lock ml1(&m); // lock m

  

  Lock ml2(ml1); // copy ml1 to ml2-what should

  // happen here?

  这是一个更一般问题的特定实例,每一个 RAII 类的作者都要面临这样的问题:当一个 RAII 对象被拷贝的时候应该发生什么?大多数情况下,你可以从下面各种可能性中挑选一个:

  禁止拷贝。在很多情况下,答应 RAII 被拷贝是没有意义的。这对于像 Lock 这样类很可能是正确的,因为同步的基本要素的“副本”很少有什么意义。当拷贝对一个 RAII 类没有什么意义的时候,你应该禁止它。Item 6 解释了如何做到这一点。声明拷贝操作为私有。对于 Lock,看起来也许像这样:

  

  class Lock: private Uncopyable { // prohibit copying - see

  public: // Item 6

  ... // as before

  };

  对底层的资源引用计数。有时人们需要的是保持一个资源直到最后一个使用它的对象被销毁。在这种情况下,拷贝一个 RAII 对象应该增加引用这一资源的对象的数目。这也就是使用 tr1::shared_ptr 时“拷贝”的含意。

  通常,RAII 类只需要包含一个 tr1::shared_ptr 数据成员就能够实现引用计数的拷贝行为。例如,假如 Lock 要使用引用计数,他可能要将 mutexPtr 的类型从 Mutex* 改变为 tr1::shared_ptr。不幸的是,tr1::shared_ptr 的缺省行为是当它所指向的东西的引用计数变为 0 的时候将它删除,但这不是我们要的。当我们使用 Mutex 完毕后,我们想要将它解锁,而不是将它删除。

  幸运的是,tr1::shared_ptr 答应一个 "deleter" 规范——当引用计数变为 0 时调用的一个函数或者函数对象。(这一功能是 auto_ptr 所没有的,auto_ptr 总是删除它的指针。)deleter 是 tr1::shared_ptr 的构造函数的可选的第二个参数,所以,代码看起来就像这样:

  

  class Lock {

  public:

   explicit Lock(Mutex *pm) // init shared_ptr with the Mutex

   : mutexPtr(pm, unlock) // to point to and the unlock func

   { // as the deleter

  lock(mutexPtr.get()); // see Item 15 for info on "get"

   }

  private:

   std::tr1::shared_ptr mutexPtr; // use shared_ptr

  }; // instead of raw pointer

  在这个例子中,注重 Lock 类是如何不再声明一个析构函数的。那是因为它不再需要。Item 5 解释了一个类的析构函数(无论它是编译器生成还是用户定义)会自动调用这个类的非静态(non-static)数据成员的析构函数。在本例中,就是 mutexPtr。但是,当互斥体的引用计数变为 0 时,mutexPtr 的析构函数会自动调用的是 tr1::shared_ptr 的 deleter ——在此就是 unlock。(看过这个类的源代码的人多半意识到需要增加一条注释表明你并非忘记了析构,而只是依靠编译器生成的缺省行为。)

  拷贝底层的资源。有时就像你所希望的你可以拥有一个资源的多个副本,唯一的前提是你需要一个资源治理类确保当你使用完它之后,每一副本都会被释放。在这种情况下,拷贝一个资源治理对象也要同时拷贝被它隐藏的资源。也就是说,拷贝一个资源治理类需要完成一次“深层拷贝”。

  某些标准 string 类型的实现是由堆内存的指针组成,堆内存中存储着组成那个 string 的字符。这样的字符串对象包含指向堆内存的指针。当一个 string 对象被拷贝,这个副本应该由那个指针和它所指向的内存组成。这样的 strings 表现为深层拷贝。

  传递底层资源的所有权。在某些非凡场合,你可能希望确保只有一个 RAII 对象引用一个未加工的资源,而当这个 RAII 对象被拷贝的时候,资源的所有权从被拷贝的对象传递到拷贝对象。就像上一篇文章所说明的,这就是使用 auto_ptr 时“拷贝”的含意。

  拷贝函数(copying functions)(拷贝构造函数和拷贝赋值运算符)可能是由编译器生成的,所以除非编译器生成的版本所做的事正是你所要的,你应该自己编写它们。在某些情况下,你也要支持这些函数的泛型化版本。

  Things to Remember

  ·拷贝一个 RAII 对象必须拷贝它所治理的资源,所以资源的拷贝行为决定了 RAII 对象的拷贝行为。

  ·普通的 RAII 类的拷贝行为不接受拷贝和进行引用计数,但是其它行为是有可能的。


上一篇:为Windows窗口标题栏添加新按钮 人气:285
下一篇:C++箴言:使用对象管理资源 人气:192
浏览全部C/C++的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-7-6 飞天论坛FTBBS ASP v6.3 Build 0
2008-7-6 飞天论坛FTBBS ASP v6.3 Build 0
2008-7-6 飞天论坛FTBBS ASP v6.8 Build 0
2008-7-6 讯息内容管理系统 v2.1
2008-7-6 三五电影程序 v2.0
2008-7-6 神鹰腾讯小说小偷 v3.0
2008-7-6 EasyIDE Framework v1.0 Build 2
2008-7-6 品告CMS系统(电影版) v0.9
2008-7-6 QQ自动登录器 C# 源码 v1.0
2008-7-5 AgileMessenger即时通讯工具 v1.
2008-7-5 GoodCalculator2.0版固件计算器
2008-7-5 RepoName源地址搜索工具 v1.21b
2008-7-5 AgileMessenger即时通讯工具 v1.
2008-7-5 TouchCopy多媒体管理软件 v3.13完
2008-7-5 VideosTone视频铃声 v1.1汉化破解
2008-7-5 TouchPad触摸板 v4.44破解版
2008-7-5 VideosTone破解补丁 v1.0
2008-7-5 Feeds GoogleReader客户端 v0.4.3


  发表评论
姓 名: 验证码:
内 容:
[ 汉字翻译拼音 ] [ 广告代码 ] [ 符号对照表 ] [ 进制转换 ] [ 经典小工具 ] [ 个税计算 ] [ 汉字简繁转换 ] [ 普通单位换算 ] [ 公制单位换算 ]
[ 生辰老黄历 ] [ 国内电话区号 ] [ 国家代码与域名缩写 ] [ 文字加密解密 ] [ 健康查询 ] [ 万年历 ] [ 手机号码查询 ] [ ip搜索 ] [ Google PR查询 ]
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報