Effective C++ 读书笔记(一)让自己习惯C++

1 让自己习惯C++

条款01:  视C++为一个语言联邦
        View C++ as a federation oflanguages

 

          –  C。说到底C++仍是以C为基础。区块(blocks)、语句(statements)、预处理器(preprocessor)、内置数据类型(built-in data types)、数组(arrays)、指针(pointers)等统统来自C。局限:non-templates non-exceptions  non-overloading

          –  Object-Oriented C++。Classes(包括构造函数和析构函数),封装(encapsulation)、继承(inheritace)、多态(polymorphism)、virtual函数(晚捆绑)……等等。

          –  Template C++。泛型编程部分。

          –  STL

C++ 高效编程守则视状况而变化,取决于你使用C++的哪一部分。

 

条款02:  尽量以const,enum,inline替换#define
                    Prefer consts,enums,and inlines to #define

–  以编译器替换预处理器。即尽量少用预处理

–  #define 可能并不进入符号表(symbol table)

Const:

•   常量指针(constant pointers)

       –  例:不变的char* -based 字符串(最好使用string)
Const char* const authorName =“Scott Meyers”;

•   Class专属常量

       –  为了确保此常量至多只有一份实体,必须让它成为一个static成员:
ClassGamePlayer {
Private:
   static const int NumTurns = 5 ;   //常量声明
};


–  注意:只要不取它的地址,你可以声明并使用它们而无需提供定义。
–  如果你取某个class专属常量的地址或者编译器报错,你就必须提供定义。

                如:const intGamePlayer::NumTurns;

                   由于class常量已在声明时获得初值(static),因此定义时不用再设初值。如果编译器还不允许这样,可以使用在声明外面定义赋予初值。如:const int GamePlayer::NumTurns = 5;如果还是报错,可以选择用 enum 关键字。

           如:enum{ NumTurns =5};…

•   Template Inline代替宏

#define CALL_WITH_MAX(a,b)    f((a) > (b)) ? (a) :(b))
int a = 5,b = 0
CALL_WITH_MAX(++a,b);   //a被累加两次
CALL_WITH_MAX(++a,b+10);//a被累加一次


template<typename T>
inline void callWithMax(cosnt T &a, cosnt T &b)
{
  f(a > b ? a : b);
}


enum

      1  比较像#define而不像const。取一个enum的地址不合法,所以可以防止pointer或reference指向你的某个整数常量。

      2  模板元编程的基础技术


  • 对于单纯常量,最好以const对象或enums替换#defines;

  • 对于形似函数的宏,最好改用inline函数替换#defines。

 

条款03:  尽可能使用const
                    Use const whenever possible

–  如果关键字const出现在星号左边,表示被指类型是常量;如果出现在星号右边,表示指针自身是常量;如果在星号两边,表示被指类型和指针两者都是常量

–  Const最具有代表性的是函数声明时的应用。Const可以和函数返回值、各参数、函数自身产生关联。

–  令函数返回一个常量值,往往可以降低因客户错误而造成的意外,而不至于放弃安全性和高效性。

                If(a * b = c)

–  Const 成员函数

•    1)它们使class接口比较容易理解。
•    2)它们使“操作const对象”成为可能。

–  如果函数的返回类型是个内置类型,那么改掉函数返回值就不可能合法。

–  Bitwise constness(physical constness)

•                  成员函数只有在不更改对象的任何成员变量(static除外)时才可以说是const。也就是说它不更改对象内任何一个位(bit)。

–  Logical constness

•                    一个const成员函数可以修改它所处理的对象内某些bits,但只有在客户端侦测不出的情况下才可以。

–  Mutable(可变的)关键字可以释放掉non-static成员变量的bitwise constness约束;

–  在const和non-const成员函数中避免重复

                    Const成员函数调用non-const成员函数是一种错误行为,因为对象有可能因此被改动。

–  Const_cast

•    用法:const_cast<type_id>(expression)

                –     该运算符用来修改类型的const或volatile属性。

                –  常量指针被转化成非常量指针,并且仍然指向原来的对象;

                –  常量引用被转换成非常量引用,并且仍然指向原来的对象;

                –  常量对象被转换成非常量对象;

 –  Static_cast

•     用法:static_cast<type_id>(expression)

                  •       该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。

  • 将某些东西声明为const可帮助编译器侦测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体;

  • 编译器强制实施bitwise constness,但你编写程序时应该使用“概念上的常量性”(conceptual constness);

  • 当cosnt和non-const成员函数有着实质等价的实现时,non-const版本调用const版本可避免代码重复。

条款04:  确定对象被使用前已被初始化
                    Make sure that objects are initialized beforethey’re used

–  读取未初始化的值会导致不明确的行为。

 

l  对象的初始化何时一定发生,何时不一定发生。

           –  对于无任何成员的内置类型,必须手工完成此事

           –  对于内置类型以外的任何其他东西,初始化责任落在构造函数(constructors)身上。确保每一个构造函数都将对象的每一个成员初始化。

           –  C++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前。

           –  初始化列表免于先调用 default构造函数然后再调用赋值操作符,只需调用一次拷贝构造函数。更高效。

           –  构造函数的最佳写法是,使用 member initialization list(成员初始化表)如:

ABEntry::ABEntry(char&name,char& address,list &phones)
 :theName(name),theAddress(address),thePhones(phones)
{
…….
}

•    编译器会为用户自定义类型(user-definedtypes)之成员变量自动调用default构造函数--- 如果那些成员变量在“成员初始化列表”中没有被指定初值的话。
•    成员变量是 const references,它们就一定需要初值,不能被赋值。
•    C++有着十分固定的“成员初始化次序”。Base classes 更早于其derived classes 被初始化,class的成员变量总是以其声明次序被初始化
•    Static 对象,其有效时间从被构造出来直到程序结束为止,因此stack和heap-based对象被排除。
–  C++对于定义于不同的编译单元内的non-localstatic对象的初始化相对次序并无明确定义
•   小方法:将每一个non-localstatic对象放到自己的专属函数内(该对象在此函数内被声明为static),这些函数返回一个reference指向它所含的对象。

•    为内置对象进行手工初始化,因为C++不保证初始化它们;

•    构造函数最好使用成员初始化列表,而不要在构造函数本体内使用赋值操作。初始化列表列出的成员变量,其排列次序应该和它们在类中的声明次序相同;

•    为免除“跨编译单元之初始化次序”问题,请local static对象替换non-local static对象。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值