More effective c++ 条款10(下)

原创 2001年10月10日 18:24:00

条款10:在构造函数中防止资源泄漏(下) 

你可能已经注意到BookEntry构造函数的catch块中的语句与在BookEntry的析构函数的语句几乎一样。这里的代码重复是绝对不可容忍的,所以最好的方法是把通用代码移入一个私有helper function中,让构造函数与析构函数都调用它。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

这就行了,但是它没有考虑到下面这种情况。假设我们略微改动一下设计,让theImage theAudioClip是常量(constant)指针类型:

};

必须通过BookEntry构造函数的成员初始化表来初始化这样的指针,因为再也没有其它地方可以给const指针赋值(参见Effective C++条款12)。通常会这样初始化theImagetheAudioClip

这样做导致我们原先一直想避免的问题重新出现:如果theAudioClip初始化时一个异常被抛出,theImage所指的对象不会被释放。而且我们不能通过在构造函数中增加trycatch 语句来解决问题,因为trycatch是语句,而成员初始化表仅允许有表达式(这就是为什么我们必须在 theImage theAudioClip的初始化中使用?:以代替if-then-else的原因)。

无论如何,在异常传递之前完成清除工作的唯一的方法就是捕获这些异常,所以如果我们不能在成员初始化表中放入trycatch语句,我们把它们移到其它地方。一种可能是在私有成员函数中,用这些函数返回指针,指向初始化过的theImage theAudioClip对象。

上面的程序的确不错,也解决了令我们头疼不已的问题。不过也有缺点,在原则上应该属于构造函数的代码却分散在几个函数里,这令我们很难维护。

更好的解决方法是采用条款9的建议,把theImage theAudioClip指向的对象做为一个资源,被一些局部对象管理。这个解决方法建立在这样一个事实基础上:theImage theAudioClip是两个指针,指向动态分配的对象,因此当指针消失的时候,这些对象应该被删除。auto_ptr类就是基于这个目的而设计的。(参见条款9)因此我们把theImage theAudioClip raw指针类型改成对应的auto_ptr类型。

这样做使得BookEntry的构造函数即使在存在异常的情况下也能做到不泄漏资源,而且让我们能够使用成员初始化表来初始化theImage theAudioClip,如下所示:

在这里,如果在初始化theAudioClip时抛出异常,theImage已经是一个被完全构造的对象,所以它能被自动删除掉,就象theName, theAddressthePhones一样。而且因为theImage theAudioClip现在是包含在BookEntry中的对象,当BookEntry被删除时它们能被自动地删除。因此不需要手工删除它们所指向的对象。可以这样简化BookEntry的析构函数:

这表示你能完全去掉BookEntry的析构函数。

综上所述,如果你用对应的auto_ptr对象替代指针成员变量,就可以防止构造函数在存在异常时发生资源泄漏,你也不用手工在析构函数中释放资源,并且你还能象以前使用非const指针一样使用const指针,给其赋值。

在对象构造中,处理各种抛出异常的可能,是一个棘手的问题,但是auto_ptr(或者类似于auto_ptr的类)能化繁为简。它不仅把令人不好理解的代码隐藏起来,而且使得程序在面对异常的情况下也能保持正常运行。

《More Effective C++》条款27:如何让类对象只在栈(堆)上分配空间?

昨天一个同学去网易面试C++研发,问到了这么一个问题:如何限制一个类对象只在栈(堆)上分配空间? 一般情况下,编写一个类,是可以在栈或者堆分配空间。但有些时候,你想编写一个只能在栈或者只能在堆上面分...
  • hxz_qlh
  • hxz_qlh
  • 2013年10月26日 21:27
  • 6092

Effective C++——条款10条,条款11和条款12(第2章)

条款10:    令operator=返回一个reference to *this Have assignment operators return a reference to *this ...
  • yiranant
  • yiranant
  • 2015年08月29日 23:35
  • 605

Effective C++ 条款10

令operator=返回一个reference to *this将operator=返回一个reference是为了什么呢?答案很简单,就是为了实现连锁形式。什么是连锁形式,如int x,y,z;x=...
  • u011058765
  • u011058765
  • 2015年06月23日 08:23
  • 648

Effective Modern C++ 条款9补完 理解模板类型推断

http://blog.csdn.net/big_yellow_duck/article/details/52224068 看大黄鸭的《Effective Modern C++》翻译时,第9款最后有一...
  • fesdobat
  • fesdobat
  • 2017年02月05日 12:56
  • 216

Effective C++ 条款9

绝不在构造和析构过程中调用virtual函数本节有个核心的知识点就是在构造函数和析构函数中,virtual函数失去多态性。 试想一下,假设此时在构造函数和析构函数中,virtual函数没...
  • u011058765
  • u011058765
  • 2015年06月22日 11:15
  • 552

Effective Modern C++ 条款7 创建对象时区分( )和{ }

Effective Modern C++ 条款7
  • big_yellow_duck
  • big_yellow_duck
  • 2016年08月13日 22:09
  • 846

《Effective C++》:条款28-条款29

条款28避免返回handles指向对象内部成分:指的是不能返回对象内部数据/函数的引用、指针等。 条款29为异常安全而努力是值得的:指的是要有异常处理机制,避免发生异常时造成资源泄露等问题。...
  • KangRoger
  • KangRoger
  • 2015年02月19日 19:47
  • 1394

Effective C++ 条款2

尽量以const、enum、inline替换#define首先,大家要明白一个道理。#define是什么,有什么作用。很简单,大家都知道#define实现宏定义,如下代码:#define Flag 1...
  • u011058765
  • u011058765
  • 2015年06月19日 12:06
  • 499

《Effective C++》:条款41-条款42

条款41了解隐式接口和编译期多态 条款42了解typename的双重意义条款
  • KangRoger
  • KangRoger
  • 2015年03月10日 22:13
  • 1243

《Effective C++》:条款44-条款45

条款44将与参数无关的代码抽离templates 条款45运用成员函数模板接受所有兼容类型...
  • KangRoger
  • KangRoger
  • 2015年03月12日 22:01
  • 1508
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:More effective c++ 条款10(下)
举报原因:
原因补充:

(最多只允许输入30个字)