effective c++笔记
mengxiangying504
这个作者很懒,什么都没留下…
展开
-
条款55:让自己熟悉boost
总结:1.boost是一个社群,也是一个网站。致力于免费、源码开放、同僚复审的C++程序库开发。boost在C++标准化过程中扮演深具影响力的角色。2.boost提供许多tr1组件实现品,以及其他许多程序库。原创 2009-12-15 10:42:00 · 552 阅读 · 0 评论 -
条款49:认识模板元编程
编译器确保所有代码有效,纵使不会被执行到的代码。总结:1.模板元编程可将工作从运行期移到编译器,因而可以实现早期错误检测和更高的执行效率。2.TMP可被用来生成“基于政策选择组合”的客户定制代码,也可用来避免生成对某些特殊类型并不适合的代码。原创 2009-12-14 09:21:00 · 423 阅读 · 0 评论 -
条款39:明智而审慎的适用private继承
1.“独立非附属”empty对象往往大小不为0,通常C++官方勒令偷偷的放一个char到其中。2.EBO空白基类最优化,往往只有在单一继承中才行。总结:1.private继承意味着“根据某物实现出”,往往比复合级别低。但是当private class需要访问protected base class的成员或重新定义继承而来的virtual函数时,这么设计是合理的。2.和复合不同,pr原创 2009-12-08 17:12:00 · 456 阅读 · 0 评论 -
条款41:了解隐式接口和编译器多态
总结:1.class和template都支持接口和多态。2.对class而言接口是显示的,以函数签名为中心。多态则是通过virtual函数发生在运行期。3.对template而言,接口是隐式的,奠基于有效表达式。多态则是通过template具现化和函数重载解析发生于编译器。原创 2009-12-09 09:35:00 · 383 阅读 · 0 评论 -
条款40:明智而审慎的使用多重继承
总结:1.多重继承比单一继承复杂。它可能导致新的歧义性,和对virtual继承的需要。2.virtual继承会增加大小、速度、初始化(赋值)复杂度等成本。如果virtual base class不带任何数据,将是最具实用价值的情况。3.多重继承的确有正当用途,其中一个情节设计“public继承某个interface class”和“private继承一个协助实现的class”的两相组合原创 2009-12-09 09:11:00 · 394 阅读 · 0 评论 -
条款42:了解typename的双重意义
总结:1.声明template参数时,前缀关键字class和typename可呼唤2.请使用typename标示嵌套从属类型名称,但不得在base class lists(基类列)和member initialization list(成员初值列)内以它作为base class修饰符。原创 2009-12-09 17:42:00 · 334 阅读 · 0 评论 -
条款38:通过复合塑模出has-a和根据某物实现出
STL中set的实现往往带来“每个元素耗用三个指针”的开销。总结:1.复合的意义和public继承完全不同2.在应用域复合意味着has-a,在实现域复合意味着“根据某物实现出”。原创 2009-12-07 10:15:00 · 359 阅读 · 0 评论 -
条款37:绝不重新定义继承而来的缺省参数值
总结:1.绝对不要重新定义继承而来的缺省参数值,因为缺省参数值是静态绑定的,而virtual函数--你唯一需要覆写的东西--是动态绑定。原创 2009-12-07 10:04:00 · 328 阅读 · 0 评论 -
条款36:决不重新定义继承而来的non-virtual函数
总结:如题原创 2009-12-07 09:54:00 · 274 阅读 · 0 评论 -
条款43:学习处理模板化基类内的名称
总结:可在derived class template 中通过"this"指涉base class template的成员名称,另外还可以使用using声明式。这两种方法比较好。第三种是明白指出被调用的函数位于base class内,base::func,但是这样会关闭“virtual绑定行为”。原创 2009-12-11 09:23:00 · 445 阅读 · 0 评论 -
条款45:将与函数无关的代码抽离template
总结:1.Template生成多个class和多个函数,所以任何template的代码都不该与造成代码膨胀的template参数产生相依关系。2.因非类型模板参数造成的代码膨胀,往往可以消除,作法是以函数参数或是class成员变量来取代该参数。3.因类型模板参数造成的代码膨胀,往往可降低,作法是以带有完全相同二进制表述的具现类型共享实现码。原创 2009-12-11 09:57:00 · 438 阅读 · 0 评论 -
条款45:运用成员函数模板接受所有兼容类型。
生命了一个泛化copy构造函数,当类型T和Y相同时,泛化copy构造函数会被具现为“正常的”copy构造函数。那么究竟编译器会暗自生成一个copy构造函数?或当某个tr1::shared_ptr对象根据另一个同型的tr1::shared_ptr对象展开构造行为时,编译器会将“泛化copy构造函数模板”具现化呢? 如果自己不定义的copy构造函数的话,就会调用泛化copy构造函数,如果自己原创 2009-12-13 18:03:00 · 442 阅读 · 0 评论 -
条款49:了解new handler的行为
总结:1.set_new_handler允许用户指定一个函数,当内存分配无法满足时调用。2.nothrow new是一个颇为局限的工具,因为它只适用于内存分配;后继的构造函数调用还是可能抛出异常。原创 2009-12-14 18:47:00 · 446 阅读 · 0 评论 -
条款54:让自己熟悉包括TR1在内的标准程序库
总结:1.C++标准程序库的主要机能由STL、iostreams、locales组成。并包括C99标准程序库。2.TR1添加了智能指针、一般化函数指针、hash-based容器、正则表达式,以及另外10个组件的支持。3.TR1自身只是一个规范。为获得tr1提供的好处,你需要一份实物。一个好的实物来源是boost。原创 2009-12-15 10:15:00 · 456 阅读 · 0 评论 -
条款51:编写new和delete需固守常规
如果被删除的对象派生自某个base class而后者没有virtual析构函数,那么c++传给operator delete的size_t的数值可能不正确。总结:1.operator new内应该有一个无穷循环,并在其中尝试分配内存,如果分配失败,就调用new handler。它也应该有能力处理0 bytes申请。class版本还需要处理“比正确大小更大的(错误)申请”。2.op原创 2009-12-15 08:31:00 · 419 阅读 · 0 评论 -
条款50:了解new和delete的合理替换时机
总结:有许多理由需要自己写一个自定义的new和delete,包括改善性能,对heap运用错误进行调试、收集heap使用信息等。原创 2009-12-14 19:20:00 · 506 阅读 · 0 评论 -
条款53:不要轻忽编译器的警告
总结:1.严肃对待编译器发出的警告信息。努力在你的编译起的最高(最苛刻)警告级别下争取“无任何警告”的荣誉2.不要过度依赖编译器的警告能力,因为不同的编译器对待警告的态度不同。一旦移植到另一台编译器上,你所依赖的警告信息可能消失。原创 2009-12-15 09:41:00 · 401 阅读 · 0 评论 -
条款52:写了placement new也要写placement delete
总结:1.当你写一个placement new,请确定也写出对应的placement delete。如果没这样做,你的程序可能会出现微弱时断时续的内存泄漏。2.当你写placement new和placement delete时,请确定不要无意识的(非故意的)遮掩了他们的正常版本。原创 2009-12-15 08:57:00 · 551 阅读 · 0 评论 -
条款47:需要类型转换时请为模板定义非成员函数
总结:当我们编写一个class template时,而它所提供之“与此template相关的”函数支持“所有参数之隐式类型转换”时,请将那些函数定义为“class template内部的friend函数”原创 2009-12-13 19:32:00 · 326 阅读 · 0 评论 -
条款48:请使用traints classes表现类型信息
总结:1.Traints classes使得“类型相关信息”在编译器可用。它们以template和“template特化”来实现。2.整合重载技术后,traints classes可能在编译器对类型执行if...else判断。原创 2009-12-14 09:01:00 · 734 阅读 · 0 评论 -
条款32:确定你的public继承塑模出is-a关系
classes之间的关系:is-a、has-a、is-implemented-in-terms-of总结:“public继承”意味is-a。适用于base classes身上的每一件事情一定也适用于derived classes身上,因为每一个derived class对象也都是一个base class对象。原创 2009-12-06 21:59:00 · 310 阅读 · 0 评论 -
条款31:将文件间的编译依存关系降至最低
1.如果使用object reference或object pointers可以完成任务,就不要使用objects。你可以只靠一个类型声明式就定义出指向该类型的references和pointers;但如果定义某类型的objects,就需要用到该类型的定义式。2.如果能够,尽量以class声明式替换class定义式。注意,当你生命一个函数而它用大某个class时,你并不需要改class的定义;原创 2009-12-06 16:09:00 · 446 阅读 · 0 评论 -
条款22:将成员变量声明为private
总结: 1.切记将成员变量声明为private。这可赋予客户访问数据的一致性、可细微划分访问控制、允诺约束条件得到保证,并提供class作者以充分的实现弹性。 2.protected并不比public更具封装性。原创 2009-11-16 20:16:00 · 352 阅读 · 0 评论 -
条款21:必须返回对象时,别妄想返回其reference
总结: 绝不要返回pointer或reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,或返回reference或pointer指向一个local static对象而有可能同时需要多个这样的对象。原创 2009-11-16 20:06:00 · 496 阅读 · 0 评论 -
条款20:宁以pass-by-reference-to-const替换pass-by-value
一、为什么不是pass-by-reference而是pass-by-reference-to-const 原先的pass-by-value函数接受了一个参数,进行的操作都是在副本上做的。因此调用者知道函数内绝不会对传入的实参做任何改变。所以这里要加上 const。 二、总结 1.尽量以pass-by-reference-to-const 代替pass-by-value。前原创 2009-11-09 14:09:00 · 367 阅读 · 0 评论 -
条款19:设计class犹如设计type
class的设计就是type的设计。在定义一个新type之前,请考虑一下主题: 1.新type的对象应该如何被创建和销毁? 2.对象的初始化和赋值该有什么样的区别? 3.新type的对象如果被pass-by-value,意味着什么?这决定了copy构造函数的实现。 4.什么是新type的“合法值”? 5.你的新type需要配合某个继承图系么原创 2009-11-09 14:00:00 · 378 阅读 · 0 评论 -
条款15、在资源管理类中提供对原始资源的访问
总结:1、API往往要求访问原始资源(raw resource),所以每一个RAII class应该提供一个“取得其所管理之资源”的方法;2、对原始资源的访问可能经由显示转换或隐式转换。一般而言显示转换比较安全,但隐式转化对客户比较方便。原创 2009-10-29 11:09:00 · 356 阅读 · 0 评论 -
条款14、 在资源管理类中小心copying行为
一.RAII对象被复制时,采用的方法1.常用1)禁止复制 2)对底层资源适用“引用计数法”(这里可以适用tr1::shared_ptr,但是要适用“删除器"(deleter)2.其他1)复制底层资源(深度拷贝) 2)转移底层资源的所有权二.总结1、复制RAII对象必须一并复制他所管理的资源,所以资源的copying行为决定RAII对象的copying行为;原创 2009-10-27 11:22:00 · 373 阅读 · 0 评论 -
条款16:成对适用new和delete时要采用相同形式
一、new和delete的相关注意点1、new和delete时发生了什么 当使用new,有两件事发生。第一,内存被分配出来;第二,针对此内存会有一个(如果new数组的话,会更多)构造函数被调用。 当使用delete,也有两件事。第一,针对此内存有一个(或更多)析构函数被调用;第二,内存被释放。2、以下行为未定义 T * p_t = new T; ...原创 2009-10-29 11:28:00 · 445 阅读 · 0 评论 -
条款17:以独立语句将newed对象置入智能指针
一、原因int priority();void processWidget(std::tr1::shared_ptr pw, int priority); 有调用: processWidget(std::tr1::shared_ptr(new Widget), priority()); 在调用ProcessWidget之前,编译器必须创建代码,做以下三件事:原创 2009-10-29 14:11:00 · 369 阅读 · 0 评论 -
条款23:宁以non-member、non-friend替换member函数
一、代码实现的弹性与封装之间的关系 愈多东西被封装,代码实现和变化的弹性愈大。 原因:如果某些东西被封装,它就不再可见。愈多东西被封装,愈少人可以看见它。而愈少人可以看到它,我们就有愈大的弹性区变化它,因为我们的改变仅仅直接影响看到改变的那些人事物。因此,愈多东西被封装,我们改变那些东西的能力愈大。这就是我们首先推崇封装的原因:它使我们能够改变事物而只影响有限客户。二、总原创 2009-11-16 20:19:00 · 415 阅读 · 0 评论 -
条款24:若所有参数皆需类型转换,请为此采用non-member函数
一、 如: class Rational { .... }; 要想以下操作: Rational a; Rational rst = a * 2; Rational rst1 = 2*a; 就是需要一个operator*函数,其参数都需要类型转换二、总结1.可以避免friend 函数时尽量避免2.如果你需要为某个函数的所有原创 2009-11-18 20:51:00 · 362 阅读 · 0 评论 -
条款25:考虑写出一个不抛异常的swap函数
一、杂项 1.通常我们不能够(不被允许)改变std命名空间内的任何东西,但可以(被允许)为标准templates(如swap)制造特化版本。 2.koening lookup法则 namespace myspace{ class a {}; class b {}; template func(原创 2009-11-18 20:57:00 · 435 阅读 · 0 评论 -
条款30:透彻了解inlining的里里外外
1.所有对virtual函数的调用都使inlining落空2.编译器通常不对“通过函数指针而进行的调用”实施inlining3.大部分调试器面对inline函数都束手无策。80-20发法则平均而言一个程序往往将80%得执行时间花费在20%的代码上。总结:1.将大多是inlining限制在小型、被频繁调用的函数身上。这可使日后的调试过程和二进制升级更容易,也可使潜在的代码膨胀问题原创 2009-12-06 16:00:00 · 259 阅读 · 0 评论 -
条款35:考虑virtual函数以外的其他选择
1.tr1::function2.tr1::bind总结:1.virtual函数的替代方案包括NVI手法和Strategy设计模式的多种形式。NVI手法自身是一个特殊形式的Template Method设计模式2.将机能从成员函数移到class外部函数,带来的缺点是:非成员函数无法访问class的non-public3.tr1::function的行为就像一般的函数指针。这样的原创 2009-12-07 09:02:00 · 347 阅读 · 0 评论 -
条款34:区分接口继承和实现继承
“提供缺省实现给derived classes,但除非它们明确要求否则免谈”的实现方法有:1.以不同的函数分别提供接口和实现2.利用“pure virtual函数必须在derived classes中重新声明,但它们可以拥有自己的实现”这一事实。总结:1.接口继承和实现继承不同。在public继承之下,derived classes总是继承base class的接口。2.pur原创 2009-12-06 22:08:00 · 263 阅读 · 0 评论 -
条款33:避免遮掩继承而来的名称
如果你正在使用public继承而又不继承那些重载函数,就是违反了base和derived classes之前的is-a关系,is-a是public继承的基石。总结:1.derived classes内的名称会遮掩base classes内的名称。在public继承下从来没有人希望如此。2.为了让被遮掩的名称再见天日,可使用using声明式或转交函数。原创 2009-12-06 22:04:00 · 268 阅读 · 0 评论 -
条款29:为异常安全努力是值得的
1.copy and swap2.pImpl idiom总结:1.异常安全函数即使发生异常也不会造成资源泄露或是数据结构败坏。这样的函数区分为3中安全保证:基本保证、强烈保证、不抛出异常2.强烈保证往往能通过“copy and swap”实现出来,但强烈保证并非对所有函数都可实现或具备现实意义3.函数提供的“异常安全保证”通常最高等于其所调用之各个函数的“异常安全保证”中的最弱原创 2009-12-04 09:53:00 · 367 阅读 · 0 评论 -
条款28:避免返回handles指向对象内部成分
1. handles:引用、指针、迭代器。 若返回的handles前没加const,成员变量的封装性最多只等于“返回其handles”的函数的访问级别。若const成员函数传出一个非const引用,那么这个函数的调用者可以修改成员变量,这与const成员函数的意义相矛盾。 就算返回的是const handles,但可能导致dangling handles。例如:原创 2009-11-29 13:51:00 · 409 阅读 · 0 评论 -
条款27: 尽量少做转型操作
一、 Base base; // Derived * p_derived = &base; //不能通过编译,旧式转型无法执行“向下转型” Derived * p_derived = static_cast(&base); //可以编译通过,但是不是“安全的向下转型”,dynamic_cast可以做到二、1.如果可以,尽量避免转型,特别是在注重效率的代码中避免使用dynamic原创 2009-11-26 21:23:00 · 448 阅读 · 0 评论