博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Effective C++ 3.资源管理
阅读量:5896 次
发布时间:2019-06-19

本文共 2691 字,大约阅读时间需要 8 分钟。

资源管理

条款13: 以对象管理资源

【Problem】

void f(){    Investment *pInv = createInvestment();          ...  /* 这里存在诸多“不定因素”,造成 "delete pInv"得不到执行,存在内存泄露的可能。*/   delete pInv;}

【Solution. 1】

使用auto_ptr智能指针确保资源的释放,避免内存泄露

void f(){    std::auto_ptr
pInv(createInvestment()); ... /*函数退出之前,经由auto_ptr的析构函数自动删除pInv指针*/}

【Key Points】

“以对象管理资源”的两个关键想法:

1. 获得资源后立刻放进管理对象内(如auto_ptr)
2. 管理对象运用析构函数确保资源被释放

【Attention】

auto_ptr的限制,举例:

std::auto_ptr
pInv1(createInvestment()); //pInv1指向createInvestment()返回值;std::auto_ptr
pInv2(pInv1); //pInv2指向对象,而pInv1被设为NULL;pInv1 = pInv2; //pInv1指向对象,而pIn2被设为NULL;

受auto_ptr管理的资源必须绝对没有一个以上的auto_ptr同时指向它。

STL容器要求其元素发挥正常的复制行为,因此这些容器容不得auto_ptr。

【Solution.2】

使用share_ptr智能指针(引用计数型智慧指针)

void f(){     ...     std::tr1::shared_ptr
pInv1(createInvestment()); //pInv1指向createInvestment()返回物; std::tr1::shared_ptr
pInv2(pInv1); //pInv1,pInv2指向同一个对象; pInv1 = pInv2; //同上,无变化 ... } //函数退出,pInv1,pInv2被销毁,它们所指的对象也竟被自动释放。

【Attention】

1. auto_ptr和tr1::share_ptr 两者都是在其析构函数内做delete而不是delete[];意味着在动态分配的array身上使用两者是个坏主意。

2. share_ptr不能管理循环引用的对象,否则造成内存泄露,举例:

class parent;class child;typedef boost::shared_ptr
parent_ptr;typedef boost::shared_ptr
child_ptr;class parent{public: children_ptr child; ~parent() { std::cout <<"destruct parent."<
child = chd; //(chd 计数 = 2) chd->parent = pat; //(pat 计数 = 2) return 0; // (函数退出时,减一后仍然大于0,无法执行析构函数,造成内存泄露)}

解决方法:

1. 当parent的生存期超过childr的生存期的时候,child内改为使用一个普通指针指向parent。
2. 使用弱引用的智能指针打破这种循环引用。举例:

暂略

条款14: 在资源管理类中小心coping行为

【Attention】

1. 复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为

2. 普遍而常见的RAII类拷贝行为是:抑制拷贝,施行引用计数法。不过其它行为也可能被实现

【Solution】

“当一个RAII对象被复制,会发生什么事?”大多数时候你会选择一下两种可能:

1. 禁止复制。如果复制动作对RAII类并不合理,你便应该禁止之。利用条款6(禁止类的copying函数)。

2. 对底层资源使用”引用计数法“。有时候我们又希望保有资源,直到它的最后一个使用者被销毁。 利用shared_ptr
3. 转移底部资源的拥有权。 利用auto_ptr
4. 复制底部资源。 利用深拷贝
``

条款15:在资源管理类中提供对原始资源的访问

【Problem】

需要一个函数可将RAII对象(shared_ptr)转换为其所内含之原始资源.

【Solution】

有两种做法可以达成目标:
1. 显示转换
shared_ptr和auto_ptr提供一个get成员函数,用来执行显示转换,也就是返回智能指针内部的原始指针。
shared_ptr和auto_ptr重载指针取值操作符(operator->和operator*),它们允许隐式转换至底部原始指针。
(即在对智能指针对象实施->和*操作时,实际被转换为被封装的资源的指针。)

2. 隐式转换

隐式转换可能引起“非故意之类型转换”

RAII class 设计方式class Font{public:    ...    FontHandle get() const//FontHandle是资源;显示转换函数    {        return f;    }    operator FontHandle() const//隐式转换这个值得注意,可能引起“非故意之类型转换”    {        return f;    }private:    FontHandle f; // 资源    ...};

尽量使用显示转换,减少出错的可能

条款16:成对使用new和delete时要采取相同形式

如果你在new表达式中使用[],必须在相应的delete表达式中也使用[]。

如果你在new表达式中不使用[],一定不要在相应的delete表达式中使用[]。

条款17:以独立语句将newed对象置入智能指针

转载地址:http://uvasx.baihongyu.com/

你可能感兴趣的文章
分布式缓存服务器设计原理
查看>>
Eclipse换常用的快捷键
查看>>
Windows Phone 8.1 新特性 - 控件之列表选择控件
查看>>
线程同步:互斥锁,条件变量,信号量
查看>>
【cocos2d-x 3.0-Mac配置篇】
查看>>
学习学习
查看>>
提升jQuery开发技能的教程
查看>>
Android系统自带样式(@android:style/) (转)
查看>>
Windbg符号与源码 《第二篇》
查看>>
Swift翻译之-Swift语法入门 Swift语法介绍
查看>>
(转)yarn 集群部署,遇到的问题小结
查看>>
.NET程序的性能要领和优化建议
查看>>
eclipse failed to create the java virtual machine 问题图文解析
查看>>
POJ 3614 Sunscreen 优先队列
查看>>
STM8S 独立看门狗配置及使用
查看>>
Linux常用命令_(进程管理)
查看>>
[转帖]cocos2d-x 3.0rc开发指南:Windows下Android环境搭建
查看>>
(原创)拨开迷雾见月明-剖析asio中的proactor模式(一)
查看>>
Accounting_权责发生制和收付实现值的区别(概念)
查看>>
数学图形(2.16)三维螺线
查看>>