[Effective C++ --014]在资源管理类中小心copying行为

时间:2022-11-03 16:36:35

第一节 <背景>
条款13中讲到“资源取得的时机便是初始化时机”并由此引出“以对象管理资源”的概念。通常情况下使用std中的auto_ptr(智能指针)和tr1::shared_ptr(引数智能指针)作为管理资源的对象。
事实上,这种管理方法十分有效。但是,auto_ptr和tr1::shared_ptr只能管理基于堆(heap-based)的资源,而非heap-based的资源却往往不适合。
因此,有的时候你需要建立自己的资源管理类。本文介绍的内容是在你建立自己的资源管理类时应该注意的事项。

第二节 <正文>
我们知道在C API中处理Mutex的互斥对象,有lock何unlock两个函数可用:

  void lock(Mutex* pm);            // 锁定pm指向的互斥量
void unlock(Mutex* pm); // pm指向的互斥量解锁

假设我们写了Lock类来管理锁。

class  Mutex{
public:
Mutex():Count(){}
public:
int Count;
};
void lock(Mutex* pm){pm->Count++;}
void unlock(Mutex* pm){pm->Count--;}
class Lock
{
public:
explicit Lock(Mutex* pm):mutexPtr(pm)
{lock(mutexPtr);} // 将mutexPtr指向的互斥变量加锁
~Lock(){unlock(mutexPtr);} // 将mutexPtr指向的互斥变量解锁
private :
Mutex * mutexPtr;
};

上面代码满足RAII(Resource Acquisition is Initialization)原则即,资源在获取时既是初始化时,失去时既是清理时。
想象下面的场景时,程序的输出结果是什么。

     Mutex m;
cout << "Mutex is " << m.Count << endl;
Lock m1(&m);
cout << "Mutex is " << m.Count << endl;
Lock m2(m1);
cout << "Mutex is " << m.Count << endl;
m1.~Lock();
cout << "Mutex is " << m.Count << endl;

输出结果为:

Mutex is
Mutex is
Mutex is
Mutex is

这是为什么呢?前两个0和1输出无可厚非,第三个的输出为拿m1作为实例对象去赋值给m2,操作对象为m1,不会直接影响m;第四个互斥量m的管理者m1被销毁了,那么m也就被解锁了。

在上面的例子中,m的值不断被变更,显然,这种资源的管理的方式是不合理的。

可能的解决方法:

1.禁止复制。禁止复制的做法具体的可参照条款6的说明。

class UnCopyable {
public:
UnCopyable(){}
private:
UnCopyable(const UnCopyable& ths) {
}
};
class Lock:private UnCopyable {
...
}

2.使用引用计数智能指针:tr1::shared_ptr。

从条款13我们已经知道引用计数智能指针会跟踪使用该资源的所有对象数,计数为0时,资源会被删除。注意,这里删除互斥量m不是我们所期待的,我们期待是解锁互斥量

幸运的是tr1::shared_ptr允许自定义所谓的“删除”动作,该动作是在计数为0时执行的。于是类Lock可以是下面的样子。

class Lock
{
public:
explicit Lock(Mutex* pm):mutexPtr(pm,unlock)
{lock(mutexPtr.get());} // 将mutexPtr指向的互斥变量加锁
private :
shared_ptr<Mutex> mutexPtr;
};

有没有发觉貌似少了点东西?对,析构函数没有了。因为share_ptr会帮你完成这一工作。

3.复制管理对象时也复制所管理的资源。

请回头想一个问题:为什么需要自己的资源管理类?那么,可能的理由是当不需要某个资源时,资源能被正常释放(删除,其他动作)。资源存在多个复件并不可怕,可怕的是复件在该销毁的时候却没有销毁。也就是,管理对象与所管理的资源要一一对应。为了保证这种对应关系,在复制管理对象时也复制所管理的资源。

4.转移资源的管理权。

在某些特殊场合下,你可能希望资源只被一个对象拥有,也就是管理对象在copying时要进行资源所有权的转移。从条款13中讲到的auto_ptr可以完美的实现这个需求。

■总结
1.复制管理对象时,请一并复制对象所管理的资源,资源的copy行为决定了管理对象的copy行为
2.普遍的RAII class的copy行为是抑制复制,使用引用计数

[Effective C++ --014]在资源管理类中小心copying行为的更多相关文章

  1. Effective C&plus;&plus;&lpar;14&rpar; 在资源管理类中小心copying行为

    问题聚焦:     上一条款所告诉我们的智能指针,只适合与在堆中的资源,而并非所有资源都是在堆中的.     这时候,我们可能需要建立自己的资源管理类,那么建立自己的资源管理类时,需要注意什么呢?. ...

  2. effective条款15&comma;在资源管理类中小心copying行为

    class A { private: int *p; void lock(){ cout << p << "is lock" << endl; ...

  3. 【14】在资源管理类中小心copying行为

    1.为什么要使用资源管理类? 资源管理类的思路就是,栈上的对象,封装堆上分配的资源,确保一定会释放资源.auto_ptr和shared_ptr就是资源管理类,行为上像指针. 2.auto_ptr和sh ...

  4. EC笔记:第三部分:14、在资源管理类中小心Copying行为

    场景 上一节实现了智能指针,其中的拷贝构造函数和赋值运算符是通过增加/减少指针的引用计数来操作的.但是如果是管理一个独占资源呢?我们希望在一个资源使用时被锁定,在使用完毕后被释放. #include ...

  5. 条款14:在资源管理类中小心copying行为

    请牢记: 1.复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为. 2.普遍常见的RAII class copying行为是:抑制copyin ...

  6. Effective C&plus;&plus; -----条款14&colon; 在资源管理类中小心copying行为

    复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为. 普遍而常见的RAII class copying行为是:抑制copying(使用私有继承 ...

  7. Effective C&plus;&plus; 条款13&sol;14 以对象管理资源 &vert;&vert; 在资源管理类中小心拷贝行为

    三.资源管理       资源就是一旦你使用了它,将来不用的时候必须归还系统.C++中最常用的资源就是动态内存分配.其实,资源还有 文件描述符.互斥器.图形界面中的字形.画刷.数据库连接.socket ...

  8. Effective C&plus;&plus;&lpar;15&rpar; 在资源管理类中提供对原始资源的访问

      问题聚焦:     资源管理类是为了对抗资源泄露.     如果一些函数需要访问原始资源,资源管理类应该怎么做呢?        关于资源管理的概念总是显得那么的高大上,其实只是抽象一点. 下面用 ...

  9. &lbrack;Effective C&plus;&plus; --015&rsqb;在资源管理类中提供对原始资源的访问

    引言 资源管理类是防止资源泄漏的有力武器,但是许多APIs直接指涉资源,除非你发誓永不使用这样的APIs,否则只得绕过资源管理对象(resource-managing objects)直接访问原始资源 ...

随机推荐

  1. CSS常用选择器名

    一.页面结构划分 box 盒子wrap 包裹container 容器 header 头部main 主要区域footer 底部 content 内容区域banner 横幅广告区域menu 菜单 二.模块 ...

  2. webpack进阶之插件篇

    一.插件篇 1. 自动补全css3前缀 autoprefixer 官方是这样说的:Parse CSS and add vendor prefixes to CSS rules using values ...

  3. IIS站点无法访问&period;&period;点浏览IIS窗口直接关掉

    呃..其实这个问题很简单.. 大家可以先看这位大婶写的博文.. http://blog.csdn.net/chenguang79/article/details/7220232 如果网站一访问IIS就 ...

  4. 那些一目了然的3D地质模型 【转】

    http://www.360doc.com/content/16/0830/09/14719766_586950902.shtml

  5. PHP Yii2&period;0(一):环境搭建 &amp&semi; 问题集锦

    第一节 简单认识版本的异同 (1)版本说明 在安装和使用之前,我们需要知道 PHP Yii 有两个不同的版本(Yii 1.*或者Yii 2.*),这两个版本的目录结构不一样,其具体使用方式差异较大,因 ...

  6. enable cors in spring mvc with swagger

    a. In controller add @CrossOrigin(origins = "http://localhost:8080") b. In mvc-servlet.xml ...

  7. 防止自己的网站被别人frame引用造成钓鱼

    自己负责的某一网站,最近被不法份子通过<frame>的方式引入,用户点击对方的域名后,看到的内容跟自己网站一模一样.但是右击查看源码就会发现其中的原理: <!DOCTYPE HTML ...

  8. SICP练习1&period;6-1&period;8

    1.6 死循环 1.7 #lang racket (define (square x) (* x x)) (define (sqrt-iter guess x) (if (good-enough? g ...

  9. 实例甜点 Unreal Engine 4迷你教程&lpar;6&rpar;之三个重要基础操作SpawnActor、TArray的Add和Remove

    本小节的教程需要完成前置教程:建议阅读<实例甜点 Unreal Engine 4迷你教程(5)>,因为5里面提到了本节的工程,不过也可以在不看5的前提下直接阅读本教程. 第一步:Empty ...

  10. 201521044091 java 第一周总结

    1.本周学习总结 (1)第一次开始接触java语言,有些用法还是和c和c++有点差异,需要不断去学习 (2)java其实不仅仅一种高级语言,它包括的还有它的整套体系. 2. 书面作业 1.为什么jav ...