Effective C++ 笔记

几乎所有的基类都包含虚函数。

如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚一般是个坏主意。

对于没有声明相应参数为const的函数来说,传递一个const对象是非法的。

当定义自己的赋值运算符时,必须返回赋值运算符左边参数的引用,*this。如果不这样做,就会导致不能连续赋值,或导致调用时的隐式类型转换不能进行,或两种情况同时发生。

为了高效和避免出错,请尽量使用const和inline而不用#define。

因为<<和>>的多态性,因此免除了数据类型的配对烦恼,故尽量用<iostream>而不用<stdio.h>。

因为malloc和free仅是机械地开辟内存空间,而new和delete会调用其构造函数和析构函数,并且程序员能通过对new和delete的重载来进行开辟空间的安全监测。

注意:
#define light_speedp 3e8 // m/sec (in a vacuum)
行尾的注释是成为宏的一部分的。

增加一个指针成员意味着几乎都要进行下面的工作:
    ·在每个构造函数里对指针进行初始化。对于一些构造函数,如果没有内存要分配给指针的话,指针要被初始化为0(即空指针)。
    ·删除现有的内存,通过赋值操作符分配给指针新的内存。
    ·在析构函数里删除指针。

编写安全的new和delete......这个还未能理清思路。

只要类里有指针时,就要写自己版本的拷贝构造函数和赋值操作符函数。                           

随着类越来越大,越来越复杂,它们的构造函数也越来越大而复杂,那么对象创建的代价也越来越高。养成尽可能使用成员初始化列表的习惯,不但可以满足const和引用成员初始化的要求,还可以大大减少低效地初始化数据成员的机会。

初始化列表中成员列出的顺序和它们在类中声明的顺序相同,原因是防止某些情况下会因为初始化的顺序而出错。

在赋值运算符中要特别注意可能出现别名的情况,其理由基于两点。
其中之一是效率。
    如果可以在赋值运算符函数体的首部检测到是给自己赋值,就可以立即返回,从而可以节省大量的工作,否则必须去实现整个赋值操作。
另一个更重要的原因是保证正确性。
    一个赋值运算符必须首先释放掉一个对象的资源(去掉旧值),然后根据新值分配新的资源。在自己给自己赋值的情况下,释放旧的资源将是灾难性的,因为在分配新的资源时会需要旧的资源。

    任何时候写一个函数,只要别名有可能出现,就必须在写代码
时进行处理,这是为了避免对象的意外破坏和程序的高效性。

    声明为explicit的构造函数会不能进行隐式转换。

    假设f是想正确声明的函数,c是和它相关的类:
·虚函数必须是成员函数。如果f必须是虚函数,就让它成为c的成员函数。
·operator>>和operator<<决不能是成员函数。如果f是operator>>或operator<<,让f成为非成员函数。如果f还需要访问c的非公有成员,让f成为c的友元函数。
·只有非成员函数对最左边的参数进行类型转换。如果f需要对最左边的参数进行类型转换,让f成为非成员函数。如果f还需要访问c的非公有成员,让f成为c的友元函数。
·其它情况下都声明为成员函数。如果以上情况都不是,让f成为c的成员函数。

尽量使用传引用而不传值,主要是对象创建和撤掉的开销和“切割”问题。但由于传引用也就是传指针,所以如果对象比较小的话,如char或int,传值会更高效。
阅读更多
个人分类: C/C++
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭