effective c++读书笔记(三)
来源:互联网 发布:sportsdt体育大数据 编辑:程序博客网 时间:2024/05/17 00:56
资源管理
资源就是你用了它,最后还要把它换回去。常见的资源包括:内存,文件描述器,互斥锁,图形界面中的字形和笔刷,数据库连接,以及网络sockets。
以对象管理资源
class Investment{ // ...};Investment* createInvestment();void f(){ Investment* pInv = createInvestment(); //... delete pInv;}
上述代码如果在delete前过早的执行return语句,或由于continue,goto等过早的退出。或提前抛出异常,等情况下,delete语句将不会执行,无法释放叼申请的内存,导致内存泄漏。或者由于维护人员对程序的理解不够深入,而加入了异常处理或这提前return 的语句都将导致内存泄漏的问题。
为了确保createInvestment返回的资源总是被释放。应该将资源放进对象内,当控制流离开f函数是,该对象的析构函数会自动释放那些资源。
void f(){ std::auto_prt<Investment> pInv(createInvestment()); //...}
使用上述的方法可以避免内存泄漏的问题。体现了两个关键的想法:
1:获得资源后,立刻放进管理对象内;资源取得时机辨识初始化时机。
2:管理对象运用析构函数确保资源被释放;
在资源管理类中小新coping行为
上条规则中所说的管理资源的方法都是针对heap-based类型资源的方法,但是并非所有资源都是heap-based,对于那些资源而言,智能指针就不再适合作为资源管理者。有的时候,需要自己建立自己的资源管理类。
//C API 函数处理类型为Mutex的互斥器对象。void lock(Mutex *pm);//锁定pm所指的互斥器void unlock(Mutex *pm); //将互斥器解除锁定//有时为了不忘记将一个被锁住的Mutex解锁,希望自己建立一个管理机锁class Lock{public: explicit Lock(Mutex *pm): mutexPtr(pm){ lock(MutexPtr); } ~Lock{ unlock(mutexPtr);}private: Mutex *mutexPtr;};Mutex m;//...{ Lock m1(&m); //运行完成后自动解锁}//但是当出现Lock对象复制的情况下Lock m11(&m);Lock m12(m11);
针对上面的问题有两种选择:1:禁止赋值 可以将copying操作声明为private的。2:对底层资源祭出“引用计数法”
复制底部资源:有时候,只要你喜欢,可以针对一份资源拥有任意数量的复件,需要资源管理类的唯一理由是:当不再需要某个复件时,确保把它释放了。复制资源管理对象时,进行的是深度拷贝。
转移底部资源的拥有权:有时只希望只有一个对象指向未加工资源,即auto_ptr奉行的复制意义。
coping 函数可能被编译器自动创建出来,因此除非编译器版本做了你想要的做的事情,否则你得自己编写他们。
在资源管理类中提供对原始资源的访问
一般来说可以通过资源管理类来进行处理和资源之间的所有互动,但是有的时候你必须绕开资源管理类直接访问原始资源。在此种情况下,应该在资源管理类中提供对于原始资源的访问方法,一般有显示类型转换,和隐式类型转换两种方法。显示类型转换一般情况下要比隐式转换方法更加的安全。
std::shared_ptr<Investment> pInv(createInvestment());int daysHeld(const Investment *pi);int days = daysHeld(pInv); //false
因为daysheld需要的是Investment*指针,但是传递给他的是shart_ptr的对象。
可以通过加入get成员函数进行显示的类型转换。int days = daysHeld(pInv.get());
成对使用new和delete时要采取相同形式
如果new表达式中使用[],必须响应的delete表达式中使用[]。同理反之。
以独立语句将newed对象置入智能指针
因为如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源泄漏问题。
int priority();void processWidget(std::shared_ptr<Widget>pw, int priority());processWidget(new Widget, priority()); //false 不能通过编译,因为shared_ptr构造函数需要一个原始指针,但该构造函数是个explicit构造函数,无法进行隐式转换processWidget(std::shared_ptr<Widget>(new Widget), priority()); //可能导致内存泄漏std::shared_prt<Widget> pw(new Widget);processWidget(pw, priority()); //true
processWidget(std::shared_ptr<Widget>(new Widget), priority());
编译器的执行顺序不一定,如果调用priority()函数在shared_ptr构造函数之前。然后priority()函数抛出了异常,会导致new Widget的指针丢失,导致内存泄漏。
- <<Effective C++>>读书笔记(三)
- 《Effective C++》读书笔记(三)
- 《effective C++》读书笔记(三)
- 《effective C++》读书笔记三——资源管理
- C++ 读书笔记 Effective C++(三)
- iOS-Effective Objective-C 2.0 读书笔记(三)
- 【读书笔记】Effective C++-1 让自己习惯C++(之三)
- Effective Java读书笔记三
- effective java读书笔记三
- 《Effective Java》读书笔记三
- Effective java 读书笔记( 三 )
- Effective c++读书笔记三
- Effective C++ 读书笔记(三)
- effective c++读书笔记(三)
- 【读书笔记】Effective C++-2 构造/析构/赋值运算(之三)
- 《Effective C++》读书笔记
- 《Effective C++》读书笔记
- 《Effective c++》读书笔记
- 自己总结的在编程中的一些小技巧
- Scrapy之路第一篇
- Android视图状态及重绘流程分析,带你一步步深入了解View(三)
- Sql 四大排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介
- JavaSE集合框架-01-集合框架体系及表数据结构
- effective c++读书笔记(三)
- AUTOCAD学习笔记3:常用电器元件的绘制
- Quora比赛代码学习笔记
- SpringCloud(第 028 篇)ConfigServer 配置管理微服务
- Redis的安装和部署
- Android自定义View的实现方法,带你一步步深入了解View(四)
- Linux中vim常用快捷键
- spring各个jar包的作用及功能总结
- VMware12提示 已将该虚拟机配置为使用 64 位客户机操作系统。但是,无法执行 64 位操作