effective c++ 条款

条款1:尽量用const和inline而不用#define
          以const 行使常量折叠,用inline 代替常用操作的宏定义,而且库里面有很多常用函数可用。当然不能抛弃宏,宏还是很有用滴。偶最近才发现宏的可爱之处。。。咔咔。
条款2:尽量用而不用
          iostream的 IO智能,灵活,类型安全。呃,效率要比 stdio的IO低些。
条款3:尽量用new和delete而不用malloc和free
          new/delete是转为C++设计的---它会自动调用构造析构函数。
          恩,这也会造成不必要的性能损失。当new一个自定义类型的数组时,会调用类的默认构造函数,这时构造的对象往往不是所需要的---也就是所那些默认构造函数白调用了。这个问题可用C++的定位new表达式解决,然后需要时再在分配的内存上构造对象。删除时直接删除整块内存。不过偶在VC6下测试时发现析构函数没用调用,可能析构函数需要显式调用吧,这种情况岂不是跟用malloc/free时一样,那拿定位new表达式干嘛? orz---呃,除了这两种情况,任何情况下都不应显示调用析构函数,不然你会后悔的。     
条款4:尽量使用c++风格的注释
           一条无聊的条款,使用什么注释要看程序员的喜好与具体情况的。
条款5:对应的new和delete要采用相同的形式
           就是new/delete,  new[]/delete[],  malloc/free,  calloc/free, ralloc/free必须配对。
条款6:析构函数里对指针成员调用delete
           呃,在构造函数中分配资源,在析构函数中释放资源。这个与异常,new动态分配等合作得天衣无缝。
条款7:预先准备好内存不够的情况。
           为了程序健壮点,进行错误检查是需要的。特别是new,万一抛出异常就不好玩了,虽然现在内存很便宜,很多人有海量内存。
条款8: 写operator new和operator delete时要遵循常规。        
条款9: 避免隐藏标准形式的new
条款10: 如果写了operator new就要同时写operator delete

           自己做了什么事自己最清楚,解铃还需系铃人。
条款11: 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符。
           如果你知道不遵守这条规则使偶对着仅仅1000多行的代码调试了两天,你就知道不遵循这条条款的后果了。编译器很生气,后果很严重。
条款12: 尽量使用初始化而不要在构造函数里赋值。
          对于自定义类型,在构造函数里复制会调用默认构造函数与拷贝构造函数,而那次默认构造函数的调用时不必的。所以初始话效率高的多,特别是大型复杂对象。但对于预定义类型则不需要,太多东东在初始化列表会搞的乱七八糟。
条款13: 初始化列表中成员列出的顺序和它们在类中声明的顺序相同。
           因为类数据成员是按类声明中的顺序初始化的。遵循这条条款可以避免很多可怕的运行错误。
条款14: 确定基类有虚析构函数。
           这是所有对象都能正常析构的保证。
条款15: 让operator=返回*this的引用。
          所有重载运算符的行为都必须与预定义运算符的行为一致。为了能连续调用operator=(),必须让其返回*thist引用,不能是其它。
条款16: 在operator=中对所有数据成员赋值
         对于有继承的情况,派生类的赋值运算符要调用基类的赋值运算符。保证基从类数据继承下来的数据成员正确复制。
条款17: 在operator=中检查给自己赋值的情况
          有些operator=需要先释放自己占用的资源再进行赋值操作,此时这条款就成了必须了。免得搞得半死不活。
条款18: 争取使类的接口完整并且最小。
          完整是显然的,没有完整接口的类拿来干嘛?  但完整的同时要保持的接口的最小化。类的接口太大难于掌握,而且容易引起歧义。最好是只提供一些原子操作。需要的话可提供一些常用复合操作以增加效率。
条款19: 分清成员函数,非成员函数和友元函数
条款20: 避免public接口出现数据成员

          这是所有面向对象技术所BS的行为。不但丧失了类“封装”这一重要作用,而且容易出错。。
条款21: 尽可能使用const
          在所有能用const的地方都应加上const,包括数据定义声明,类函数成员声明。这样可避免一些可怕的运行错误而不会造成性能上的损失。多打几个字的代价肯定能赚回来。
条款22: 尽量用“传引用”而不用“传值”。
            效率,效率,效率还是效率。呃,还要记住的是在能加const的地方都要加上, const引用。。。
条款23: 必须返回一个对象时不要试图返回一个引用
            这条条款是为效率狂准备的。任何时候返回一个临时对象的引用或地址都是可怕的行为。
条款24: 在函数重载和设定参数缺省值间慎重选择
条款25: 避免对指针和数字类型重载
条款26: 当心潜在的二义性。
条款27: 如果不想使用隐式生成的函数就要显式地禁止它。
            
如默认构在函数,拷贝构造函数,复制运算符,析构函数。。。。禁止很简单。声明为privated,并不提供定义。。。咔咔。。。当然有些时不能禁止的。如果不放心隐式生成的函数,那就自己提供一个。特别是有指针的时候。
条款28: 划分全局名字空间。
           
全局域只有一个。污染全局域的后果很严重。这里namespace正好派上用场了。
条款29: 避免返回内部数据的句柄。
条款30: 避免这样的成员函数:其返回值是指向成员的非const指针或引用,但成员的访问级比这个函数要低。
条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引用
             
很明显返回局部变量的引用或地址得到的将是垃圾。  函数也不应该返回new来的对象的引用或地址。函数不一定是只有你用的,使用者不知道你的函数的实现方式,当然也不会轻易的动用delete咯,这也就造成了内存泄漏。 即使使用者这是你一个人,当函数的返回值散步与程序各处时,什么时候delete不是一个容易的判断。
条款32: 尽可能地推迟变量的定义
条款33: 明智地使用内联
             
内联可以避免函数调用的开销。短小常用的函数都应该内联。如果内联函数体非常短,编译器为这个函数体生成的代码就会真的比为函数调用生成的代码要小许多。这种情况,内联这个函数将会确实带来更小的目标代码和更高的缓存命中率!但在很多情况下,那内联都会增加代码体积。在一台内存有限的计算机里,过分地使用内联所产生的程序会因为有太大的体积而导致可用空间不够。即使可以使用虚拟内存,内联造成的代码膨胀也可能会导致不合理的页面调度行为(系统颠簸),这将使你的程序运行慢得象在爬。(当然,它也为磁盘控制器提供了一个极好的锻炼方式:))过多的内联还会降低指令高速缓存的命中率,从而使取指令的速度降低,因为从主存取指令当然比从缓存要慢。          还有就是  inline   只是程序员对编译器的建议,但决定权在编译器手上,当编译器认为你的函数不适合内联时。它就会以普通函数的形式处理你的函数,这样可能会带来函数重定义的错误。         构造函数和 析构函数不适于内联,因为这些函数的代码往往比你所看到的多。       最后一个就是有静态数据成员的函数和虚函数不能作为内联函数。。。。。。。
条款34: 将文件间的编译依赖性降至最低
条款35: 使公有继承体现 "是一个" 的含义
条款36: 区分接口继承和实现继承
条款37: 决不要重新定义继承而来的非虚函数
条款38: 决不要重新定义继承而来的缺省参数值
条款39: 避免 "向下转换" 继承层次
条款40: 通过分层来体现 "有一个" 或 "用...来实现"
条款41: 区分继承和模板
条款42: 明智地使用私有继承
条款43: 明智地使用多继承
条款44: 说你想说的;理解你所说的
条款45: 弄清C++在幕后为你所写、所调用的函数
条款46: 宁可编译和链接时出错,也不要运行时出错

             运行错误当然比编译连接错误麻烦多了。可是这条款是一句废话。错误是能选择的么?ft~
条款47: 确保非局部静态对象在使用前被初始化
            
 这句话好像应该说成:非静态局部变量和动态分配的对象使用前应初始化。非静态局部变量和动态分配的变量都是为初始化的,使用前当然应该初始化咯。全局变量和静态变量自动初始化为0。
条款48: 重视编译器警告
条款49: 熟悉标准库
           
标准库是个好东东。。。。咔咔
条款50: 提高对C++的认识
           这不是废话么?呃。。。C++确实蛮复杂。 理解C++最好理解它的历史《The Design and Evolution of C++》。呃。C++标准是最权威的手册。(两个偶都不喜欢看,D&E太无聊,标准太拗口。。。。   到时《The C++ programing language》《C++primer》《Inside The C++ Object Model》 和“深入C++系列”都很不错,呃。。。


More Effective C++ 35 条款





一,基础议题(basics)
条款1:仔细区别 pointers 和 references(Distinguish between pointers and references)

            一个基本的语法问题。
条款2:最好使用 C++ 类型转换运算符(Prefer C++-style casts)
           C++的类型转换运算符安全,容易解析,分工精细,虽然要打多点字。
条款3:绝对不要以 polymorphically(多态)方式來处理数组(Never treat arrays polymorphically)
             数组都是单一类型的,好像没有必要用多态方式处理。array[i] 与 array[i+1]之间的偏移量是静态决议的,so,不要以多态方式处理。呃,如果是指针数组例外,声明一个基类指针数组,仍然可以完美地以多态方式处理。。。。咔咔。。。
条款4:非必要不使用 default constructor(Avoid gratuitous default constructors)
          很多类使用默认构造函数不能构造有意义的对象,所以应该避免。此处出现的问题是:没有默认构造函数不能使用动态分配数组,也就不能使用许多标准库的容器。

二,运算符(operators)
条款5:对类型转换函数保持警觉(Be wary of user-defined conversion functions)

            自定义类型转换函数容易引起一起很难发觉的运行错误,应该避免使用。使用重载运算符或函数以取代自定义类型转换函数。STL就是这样干的。
条款6:区别 increment/decrement 运算符的前序(prefix)和后序(postfix)型式(Distinguish between prefix and postfix forms of increment and decrement operators)
             不只是重载时语法的不同。还有效率的不同。前置的返回引用,后置的返回临时对象。这也意味后置的不能连续调用。
条款7:千万不要重载 &&, ||, 和 or,(逗号) 运算符(Never overload &&, ||, or ,)
条款8:了解各种不同意义的 new 和 delete(Understand the different meanings of new and delete)

三,异常(Exceptions)

条款9:利用 destructors 避免资源泄漏(Use destructors to prevent resource leaks
)
                     在构造函数分配资源,在析构函数中释放资源。C++保证delete调用,异常抛出时会调用类析构函数释放资源
款10:在 constructors 內阻止资源的泄漏(resource leaks)(Prevent resource leaks in constructors)
条款11:禁止异常(exceptions)流出 destructors 之外(Prevent exceptions from leaving destructors) 虚构函数释放资源,前提是对象已经被构造。若constructors内抛出异常,此时对象尚未构造,析构函数也就不会被调用。所以应该禁止异常流出构造函数。
条款12:了解「抛出一个异常」与「传递一个参数」或「调用一个虚拟函数」之间的差异(Understand how throwing an exception differs from passing a parameter or calling a virtual function)
条款13:以 by reference 方式捕捉异常 (exceptions Catch exceptions by reference)

              效率,效率,效率。。。。。。。
条款14:明智运用 exception specifications (Use exception specifications judiciously)
条款15:了解异常处理(exception handling)的成本 (Understand the costs of exception handling)

四,效率(Efficiency)

条款16:謹記 80-20 法則(Remember the 80-20 rule)

              80的时间用来运行20%的代码。所以优化应该针对那20%的代码。
条款17:考虑使用 lazy evaluation (Consider using lazy evaluation)
条款18:分期摊还預期的计算成本(Amortize the cost of expected computations)
条款19  了解临时对象的来源(Understand the origin of temporary objects)

              函数调用,返回时容易产生临时对象。
条款20:协助完成「返回值优化(RVO)」(Facilitate the return value optimization)
条款21:利用多载技术(overload)避免隱式类型转换(Overload to avoid implicit type conversions)
条款22:考虑以复合形式的运算符(op=)取代其型式(op) (Consider using op= instead of stand-alone op)

              原因很简单,op=不用返回临时对象。a=b+c+d+e;可转换为 ;     a=b; a+=c; a+=d; a+=e;
条款23:考虑使用其他程序库(Consider alternative libraries)
条款24:了解 virtual functions、multiple inheritance、virtual base classes、runtime type identification 所需的成本(Understand the costs of virtual functions, multiple inheritance, virtual base classes, and RTTI)

                关于vptr和vbtl。。。。。。太长,不写了。。。。

五,技术(Techniques,又称 Idioms 或 Pattern)

条款25:将 constructor 和 non-member functions 虚拟化(Virtualizing constructors and non-member functions)

               用一个成员函数将他们包装起来就行了。(visual consturtor 返回动态对象地址)
条款26:限制某个 class 所能产生的对象数量(Limiting the number of objects of a class)
条款27:要求(或禁止)对象产生于 heap 之上(Requiring or prohibiting heap-based objects)
条款28:Smart Pointers(灵巧指针) 
条款29:Reference counting(引用计数) 
条款30:Proxy classes(代理类) 
条款31:让函数根据一个以上的对象列别來決定如何虚拟化(Making functions virtual with respect to more than one object)

                模拟编译器多态的实现。 
typedef pair ps;    map(string为所有对象类名,funtion pointer 为需要虚拟化的函数,静态成员函数)。然后用typeid取得两个参数对象的类名,再根据类名在map中取得正确的函数指针,调用。。。。。。咔咔,就是这么简单。

六,杂项讨论(Miscellany) 
条款32:在未來时态开发程序(Program in the future tense)
条款33:將非末端类(non-leaf classes)设计为抽象类(abstract classes)(Make non-leaf classes abstract)
条款34:如何在同个程序結合 C++ 和 C (Understand how to combine C++ and C in the same program)
条款35:让自己习惯使用标准的 C++ 語言(Familiarize yourself with the language standard)
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值