Effective c++学习笔记

来源:互联网 发布:上海数据港 股东 编辑:程序博客网 时间:2024/05/21 06:42

1 尽量用constinline而不用#define

    #define指令的另一个用法是用它来实现那些看起来象函数而又不会导致函数调用的宏。如 #define max(a,b)  ((a) > (b) ? (a) :(b))

 

2 头文件使用#include<iostream>,得到的是置于名字空间std下的iostream库的元素;如果使用#include <iostream.h>,得到的是置于全局空间的同样的元素。

 

3 尽量用newdelete而不用mallocfree

Mallocfree会产生问题的原因在于他们太简单:他们不知道构造函数和析构函数。

用两种方法给一个包含10string对象的数组分配空间,一个用malloc,另一个用new

string *stringArray1 = static_cast<string*>(malloc(10*sizeof(string)));

    string *stringArray2 = new string[10];

其结果是,stringArray1 确实指向的是可以容纳 10 string 对象的足够空间,但内存里并没有创建这些对象。而且,如果你不从这种晦涩的语法怪圈(详见条款 M4 M8 的描述)里跳出来的话,你没有办法来初始化数组里的对象。换句话说,stringArray1 其实一点用也没有。相反,stringArray2 指向的是一个包含 10 个完全构造好的 string 对象的数组,每个对象可以在任何读取 string 的操作里安全使用。

 

内存管理:

C++中涉及的内存的管理问题可以归纳为两方面:正确地得到它和有效地使用它。

正确地得到”的意思是正确地调用内存分配和释放程序;而“有效地使用”是指写特定版本的内存分配和释放程序。

7 产品的调试状态下assert断言有用;但的产品的发布状态下assert相当于一条空语句。

预先准备好内存不足的情况:

如果想用一个很简单的出错处理方法,可以这么做:当内存分配请求不能满足时,调用你预先指定的一个出错处理函数。这个方法基于一个常规,即当operator new不能满足请求时,会在抛出异常之前调用客户指定的一个出错处理函数——一般称为new-handler函数。

 

指定出错处理函数时要用到 set_new_handler 函数,它在头文件<new>里大致是象下面这样定义的:

    typedef void (*new_handler)();

new_handler set_new_handler(new_handler p) throw();

可以看到,new_handler 是一个自定义的函数指针类型,它指向一个没有输入参数也没有返回值的函数。set_new_handler 则是一个输入并返回new_handler类型的函数。

 

  set_new_handler 的输入参数是 operator new 分配内存失败时要调用的出错处理函数的指针,返回值是 set_new_handler 没调用之前就已经在起作用的旧的出错处理函数的指针。

 

11 解决指针混乱问题的方法是:只要类里有指针时,就要写自己版本的拷贝构造函数和赋值操作符函数。  对于有些类,当实现拷贝构造函数和赋值操作符非常麻烦,特别是确信程序中不会做拷贝和赋值操作的时候,可以只声明这些函数(声明为private成员)而不去定义(实现)他们。这就防止了会有人去调用它们,也防止了编译器去生成他们。

 

12 尽量使用初始化而不要在构造函数里赋值

有些情况下必须用初始化,特别是const和引用数据成员只能用初始化,不能被赋值。另外,即使是不包含const和引用成员。用成员初始化列表还是比在构造函数里赋值要好。原因在于效率。

 

13 初始化列表中成员列出的顺序和成员在类内声明的顺序一致;

 

14 确定基类有虚析构函数

  如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚一般是个坏主意。因为实现虚函数需要对象附带一些额外信息,如vptrvtbl等。

 

15 operator=返回*this的引用

在一个类C中,缺省版本的operator=函数具有如下形式:

C& C::operator=(const C&)

一般情况下几乎总要遵循operator=输入和返回的都是类对象的引用。

string&                            // 将一个string

operator=(const string& rhs);      //  赋给一个string

string&                            // 将一个char*

operator=(const char *rhs);        //  赋给一个string

请注意,即使在重载时,返回类型也是类的对象的引用。