Effective C++ 第一章 让自己习惯 C++

第一章 让自己习惯 C++(Accustoming Youself to C++)

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

C++是个多重范型编程语言,同时支持过程形式、面向对象形式、函数形式、泛型形式、元编程形式。

视C++为一个语言联邦,包括以下四个部分:

  1. C:面向过程的部分
  2. Object-Oriented C++:面向对象的部分,包括封装、继承、多态以及虚函数(动态绑定)等。
  3. Template C++:泛型编程部分
  4. STL: 融合泛型编程和OOP编程思想的C++标准模板库,包括容器、迭代器、算法以及函数对象等。

请记住:

  • C++高效编程守则视状况而变化,取决于使用的是这四个部分中的哪一部分。

条款2:尽量以const,enum,inline代替#define

宁可以编译器代替预处理器

#define即宏定义在预处理阶段进行处理,不进入记号表(symbol table)。

int a = 5, b = 0;
CALL_MAX(++a, b);       //a被累加2次
CALL_MAX(++a, b + 10);  //a被累加1次

这是不可预料的行为,因此使用内联函数来代替宏定义函数。

请记住:

  • 对于单纯常量,最好使用const对象或enum替换#defines。
  • 对于形似函数的宏,最好改用inline函数替换#defines。

条款3:尽可能使用const

const关键字告诉编译器某值应该保持不变,即为只读的。

const成员函数

两个成员函数如果只是常量性不同,可以被重载。

const成员函数代表this指针的类型为:const className &

使用const成员函数来处理const对象。

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

利用non-const版本调用const版本,再加上转型const_cast、static_cast,例如:

const char& operator[](int pos) const;//const版本

char& operator[](int pos) { //non-const版本
    return const_cast<char&> //返回值转型,移除const
     (static_cast<const className&>(*this)[pos]);//*this转型,增加const
}

但反过来使用const版本调用non-const版本则是一种错误行为。

请记住:

  • 将某些东西声明为const可以帮助编译器侦测除错误;const可以被施加在任何作用域内的对象、函数参数、函数返回类型、成员函数本身。
  • 编译器强制实施bitwise constness,但是你编写程序时应该使用“概念上的常量性”。
  • 当const和non-const成员函数有着实质等价的实现时,使用non-const版本来调用const版本可以避免代码重复。

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

永远在对象使用之前将其初始化。

  1. 对于内置类型,手动初始化。

  2. 对于非内置类型,使用构造函数进行初始化。

赋值和初始化有区别:

// 赋值,而非初始化
ABEntry(const string& name, const string& address, int num) {
        _name = name;
        _address = address;
        _num = num; 
        }
// 初始化,发生在进入构造函数本体之前
// 即成员初值列(member initialization list)
ABEntry::ABEntry(const string& name, const string& address, int num)
    : _name(name), _address(address), _num(num) { }

C++有着固定的初始化顺序:按照声明顺序进行初始化,且基类先于派生类初始化

static对象:其寿命从被构造出来直到程序结束为止。

local static object(局部静态对象):函数内的static对象。

non-local static object(非局部静态对象):非函数内的static对象,不同编译单元之间初始化次序不确定

因此,要解决non-local static object初始化次序问题,就要将non-local static object转换为local static object(使用单例模式,即封装一层函数)

class Singleton
{
public:
    static Singleton& getInstance() {
        static Singleton s;
        return s;
    }
private:
    Singleton() {}
    Singleton(const Singleton&);
    void operator=(const Singleton&);
};

请记住:

  • 为内置类型进行手工初始化,C++不保证初始化它们。
  • 构造函数最好使用成员初值列,不要在构造函数中使用赋值操作,初值列中的成员变量的顺序应该和声明顺序一致。
  • 为免除“跨编译单元之初始化次序”问题,使用返回local static对象引用的函数来代替non-local static对象。

reference

[1] Effective C++ · Scott Meyers

posted @ 2021-12-12 22:02  zju_cxl  阅读(37)  评论(0编辑  收藏  举报