条例1~5

目录

条例二

尽量用const,enum,inline,替换#define

the enum hack 补偿法

使用宏替换函数的时候务必给所有实参加上小括号

总结

条例三

const对于指针来说左定值右定向

函数返回值最好带上const,防御性编程,这样能防止某些不合法的操作

成员函数是const的意义

cont和non const 成员函数避免重复

总结

条例四

确定对象使用前已经被初始化

总结

条例五

c++默认生成的成员函数

总结


条例二

尽量用const,enum,inline,替换#define

  • 宏替换不会进符号表,会在处理源码时直接替换,若出现报错将会导致可读性差。可用常量替换宏。
  • 宏替换会导致代码量增大。
  • 宏定义不能提供任何封装性,无法define一个class的专属常量

the enum hack 补偿法

  • 一个属于枚举类型的数值可以充当int使用,可以用于数组大小的声明。这种做法类似宏替换

使用宏替换函数的时候务必给所有实参加上小括号

  • 尽量少用这种方法,可以通过模板参数加内联函数得到同样的效果

总结

  • 对于单纯的常量,最好用const 或enums  替换宏
  • 对于函数,最好用内联替换宏

条例三

const对于指针来说左定值右定向

函数返回值最好带上const,防御性编程,这样能防止某些不合法的操作

比如说不小心对函数返回值进行赋值。

成员函数是const的意义

  • 两个流行概念bitwise const 和 logical constness,前者指的是成员函数不更改对象内的任何变量。(好处是编译器至于需要检查成员变量是否有赋值动作,缺点是可以过指针绕过强行修改。比如说返回指针引用,然后客户对指针解引用并修改它的值)后者指的是const成员函数可以修改成员变量,但要在用户不知道的情况下。当你你的成员函数添加了const的时候,成员变量可能需要修改,但这时编译器坚持bitwise const,就会出现编译报错。可以用mutable释放掉non static成员变量的bitwise const约束。

cont和non const 成员函数避免重复

  • 函数传参的时候const 变量 无法调用非const的成员函数。但非const参数可以调用const成员函数,这里有权限匹配的问题,缺陷只能相等或者缩小不能放大。
  • 我们可以用非const成员函数复用const成员,提高代码的复用程度。在想要使用non const成员函数的时候,我们先可以用static cast 关键字对当前this指针添加上const属性,再复用const成员函数,最后拿到结果后再用const cast 关键字去掉const 属性。(虽然理论上non const 对象可以直接调用 const函数,但此时我们若不添加上const 属性,这调用的就是它本身也就是非const函数,就会陷入无穷递归,我们需要强制添加上const属性,这样才会调用const成员函数)
  • 注意点,只能用non const成员函数复用const 成员函数。因为const成员函数需要保证内部成员不被改变,若反着用就会存在改动风险

总结

  • 若条件允许,可以用non const 函数复用const函数
  • 编译器强制实施 bitwise constness
  • 函数尽量声明为const 可以帮助编译器检查出错误用法

条例四

确定对象使用前已经被初始化

  • 尽量使用初始化列表代替函数内初始化。因为在构造函数内部无论你是否使用初始化列表,他都会先通过初始化列表自动构造成员变量(自定义函数调用其自身的构造函数,内置类型不处理)再在函数体内部对这些成员进行复制。若我们直接调用初始化列表初始化,他将直接调用拷贝构造。这样可以从 构造函数+赋值 优化到 拷贝构造 提高效率。
  • 继承的父类成员变量优先初始化,当前成员变量后初始化。初始化列表的初始化顺序是由声明顺序决定的。与初始化列表的顺序无关。
  • 不同编译文件之间的非局部静态对象(不再函数内定义的)初始化顺序是无法确定的。这时若两个不同文件内的静态对象存在先后依赖关系,就会出现错误。这时可以通过类似单例模式解决。将非局部静态变量搬到自己的专属函数内,通过函数去调用这些静态变量,也就是让非局部静态变量成为局部静态变量。这样所另一个好处就是,若你不调用这个获取静态变量的函数,就不会产生构造和析构的成本。要点就是虽然非局部静态变量初始化顺序不可控,但是局部静态变量的初始化顺序是可控的。(但是这样做的缺点是在多线程环境下可能出现问题)

总结

  • 内置对象都要手动初始化,编译器不会保证会自动初始化
  • 最好使用初始化列表初始化,同时初始化列表的排列顺序最好的声明顺序一致
  • 多文件编译最好用静态变量替换局部静态变量,这样能确保初始化顺序

条例五

c++默认生成的成员函数

  • 空类编译器会自己生成拷贝构造,拷贝赋值,析构函数,若自己没实现析构,还会生成默认析构。
  • 拷贝构造和拷贝赋值默认是值拷贝
  •  若条件不允许,有时候编译器会拒绝生成拷贝赋值操作。当成员变量是引用的时候,当初成员变量是const,基类的拷贝赋值为私有,想要默认生成子类拷贝赋值,时编译器会拒绝赋值操作。这种情况只能自己实现拷贝赋值操作

总结

  • 编译器可以暗自生成构造,析构,拷贝,赋值等成员函数

你可能感兴趣的:(Effective,c++,c++,数据结构)