关闭

Effective C++笔记(1)

标签: Effective C++笔记c++编程编程语言面向对象
446人阅读 评论(0) 收藏 举报

0、导读 

    本书的最佳用途就是彻底了解C++如何行为、为什么那样行为,以及如何运用其行为形成优势。

     声明式(declaration)是告诉编译器某个东西的名称和类型(type),但略去细节。如:extern int x; template<typename T>; 标准函数库几乎全在std命名空间中。每个函数的声明揭示其签名式(signature),也就是参数和返回类型(std::size_t numDigits(int number;))。

    定义式(definition)的任务是提供编译器一些声明式所遗漏的细节。对对象而言,定义式是编译器为此对象分配内存的地点。对function或function template而言,定义式提供了代码本体。对class或class template而言,定义式列出他们的成员。

    初始化(initialization)是“给予对象初值”的过程。对用户自定义类型的对象而言,初始化由构造函数执行。所谓default构造函数是一个可被调用而不带任何实参者。这样的构造函数要不没有参数,要不就是每个参数都有缺省值。构造函数被声明为explicit可阻止被用来执行隐式类型转换(implicit type conversions)。explicit禁止编译器执行非预期的类型转换,鼓励使用explicit。

    copy构造函数被用来“以同型对象初始化自我对象”,copy assignment操作符被用来“从另一个同型对象中拷贝其值到自我对象”。如果一个新对象被定义,一定会有构造函数被调用,不可能调用赋值操作。如果没有新对象被定义,就不会有构造函数被调用,那么就是赋值操作被调用。copy构造函数定义了一个对象如何passed by value。

    不明确行为的结果是不可预期的,应尽量避免。C++中的接口指函数。暂时忽略线程

1、让自己习惯C++

    条款01:视C++为一个语言联邦

    C++是个多重泛型编程语言(multiparadigm programming language),支持过程形式(procedural)、面向对象形式(object-oriented)、函数形式(function)、泛型形式(generic)、元编程形式(metaprograming)的语言。把C++看成一个组合联邦,认识其主要次语言:C、object-oriented C++、template C++、STL。C++高效编程守则视状况而变化,取决于你使用C++的哪一部分。

条款02:尽量以const、enum、inline替换#define

    “宁可以编译器替换预处理器” #define定义的记号名称在编译之前可能被预处理器移走了,可能没进入记号表内。编译错误时,可能对错误毫无概念。解决之道是以常量替换宏。当以常量(const)替换#define,定义常量指针(constant pointer)在头文件中。class专属常量:为了将常量作用域限制于class内,你必须让它成为class的一个member;为确保常量至多只有一份实体,必须让它成为一个static member;如果即是常量又是static则需特殊处理。编译器需看到一个定义式,需另外提供定义式如:const  int Gameplayer::NumTurns;(放在实现文件中)如果class常量已在声明时获得初值,定义时不可以再设初值。没有所谓private #define这样的东西。

    万一你的编译器不允许“static 整数型class常量”完成“in class初值设定”,可改用所谓的“the enum hack”补偿做法。其理论基础是:“一个属于枚举类型的数值可权充int被使用”。enum hack的行为某方面说比较像#define而不像const,如果你不想让别人获得一个pointer或reference指向你的某个整数常量,enum可以实现。

    对于单纯常量,最好以const对象或enum替换#define。对于形式函数宏(macros),最好改用inline函数替换#include。

条款03:尽可能使用const

    const char *(const  data)、char * const (const pointer)

    const 最具威力的用法是面对函数声明时的应用。一个“良好的用户自定义类型”的特征是避免无端地与内置类型不兼容。

    将const实施于成员函数的目的是为了确认成员函数可作用于const对象身上。const成员的重要性:1、使class接口比较容易被理解。2、使“操作const对象”成为可能。改善C++程序效率的一个根本办法是以pass-by-reference-to-const方式传递对象,前提是有const成员函数可用来处理const对象。

    const成员函数不可以更改对象内任何任何non-static成员变量。const成员函数承诺绝不改变其对象的逻辑状态。

    将某些东西声明为const可帮助编译器侦测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复。

条款04:确定对象被使用前已先被初始化

    使用C part of C++初始化可能招致运行期成本,不初始化。永远在使用对象之前将它初始化。对于无任何内置类型,必须手工完成。如int x = 0;其他类型确保每一个构造函数都将对象的每一个成员初始化。不要混淆了赋值(assignment)和初始化(initialization)。C++对象的成员变量的初始化动作发生在进入构造函数本体之前。构造函数的一个较佳写法是:使用所谓的member initialization list成员初值列替换赋值动作。总是在初值列中列出所有成员变量,以免还得记住哪些成员变量可以无需初值。如果成员变量是const或reference,就一定需要初值,不能被赋值。

    C++有着十分固定的“成员初始化次序”:base class更早于derived class被初始化,class的成员变量总是以其声明次序被初始化。

    static对象从被构造出来直到程序结束为止,因此stack和heap-based对象被排除。C++对“定义于不同编译单元的non-local static对象”的初始化相对次序并无明确定义。多个编译单元内的non-local static对象经由“模板隐式具现化”形成。唯一需要做的是:将每个non-local static对象搬到自己的专属函数内(该对象在此函数内被声明为static),这些函数返回一个reference指向它所含的对象。然后用户调用这些函数。(non-local static对象被local static 对象替换了)。C++保证,函数内的local static对象会在“该函数被调用期间“首次遇上该对象之定义式“时被初始化。

    在程序的单线程启动阶段手工调用所有reference-returning函数,可消除与初始化有关的”竞速形势“。前提是其中有着一个对对象而言合理的初始化次序。

    为避免在对象初始化之前过早的使用它们:1、手工初始化内置型non-member对象;2、使用成员初值列对付对象的所有成分;3、在”初始化次序不确定性“(对不同编译单元所定义的non-local static对象是一种折磨)氛围下加强你的设计。

    为内置对象进行手工初始化;构造函数最好使用成员初值列,而不要在构造函数本体内使用赋值操作。初值列列出的成员变量,其排列次序应该和他么在class中的声明次序相同。为免除”跨编译单元之初始化次序“问题,请以local static对象替换non-local static对象。

   

   

   

   

   


   



   






0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:13096次
    • 积分:288
    • 等级:
    • 排名:千里之外
    • 原创:15篇
    • 转载:9篇
    • 译文:0篇
    • 评论:1条
    文章存档