【读书笔记】【Effective C++】让自己习惯 C++

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

  • C++ 并不是 C 的超集,双方都有自己独特的地方。
  • C++ 语言由四个次语言组成,每一个部分有自己独立的高效编程守则,要清楚自己运用的是哪一部分:
    • C:C++ 以 C 为基础;
    • Object-Oriented C++:也就是 C with classes 所诉求的;
    • Template C++:C++ 的泛型编程部分;
    • STL:template 程序库。

条款 02:尽量以 const、enum、inline 替换 #define

  • 尽量以编译器代替预处理器。
  • 在 C 语言中,我们一般使用宏定义 #define 语句来声明某些常量或是函数,但是 C++ 中推荐使用 const、enum、inline 等来替代 #define 的使用。
    • #define 语句在使用中有诸多不足,从原理上讲,在程序编译的预处理阶段,编译器会把 #define 声明的代码直接插入程序中。【注意这里说的直接插入:那意味着如果不加括号,一些函数操作可能会出错】
    • #define 是预处理器处理的部分,当编译出错时,不容易发现错误发生在哪里,其次由于预处理器盲目的替换,会导致目标码的增大。
  • 对于常量,用 const 或者 enum 替换 #define:
    • const 的写法要优于 #define;const std::string 的写法要优于 const char* const
    • #define 并不重视作用域,所以无法定义 class 中专属常量变量。
      • class 专属常量的获得:需要将成员声明为 static(即使给予数值,在类内仍然是声明),然后再在类外定义(如果类内已经赋值,在类外不需要再给)。
      • 但有时编译器不允许前面的类内初值设定,可以利用 enum hack 代替 static const。
      • enum 的使用更像是 #define 而不像 const,既无法获得 #define 的地址,也无法让别人获得一个 pointer 或 reference 指向 enum(因为 enum 的地址不合法)。
  • 对于形似函数的宏,改用 inline 函数替换 #define。
    • #define 的实现宏有时会带来额外的开销。

条款 03:尽可能使用 const

  • const 能修饰的东西特别多。
    • const 与指针的结合特别直观,与 STL 迭代器的结合也是一样。
    • const 在函数声明中更为方便,可以和返回值、参数、函数自身产生关联。
  • const 的习惯使用可以降低因用户错误而造成的意外。
    • 举个例子:加了 const,能避免想要键入 == 却意外键入 = 的错误。
  • 编译器强制实施 bitwise constness,但程序员编写程序时应该使用概念上的常量性(conceptual constness)。
    • const 修饰成员函数时,代表该函数内不允许修改成员函数的任何属性(即使某些属性并没有被声明为 const)。【bitwise constness】
    • mutable 关键字可以破除这个限制,即是允许程序员适当地使用 mutable 关键字来让 const 成员函数可以改变某些值。【logical constness】
    • 常量性(constness)也可以是重载的原因。
    • const 成员函数的作用:使接口容易被理解、消除误操作的隐患、使操作 const 对象成为可能。
      • 最后一个作用的意思是指,当我们创建了一个 const 对象,只能调用 const 对象的 const 成员函数。
  • 当 const 和 non-const 成员函数有着实质等价的实现时,令 non-const 版本调用 const 版本可避免代码重复。

条款 04:确定一个对象被使用前已经先被初始化了

  • 为内置型对象进行手工初始化,因为 C++ 不保证初始化它们。
  • 对于 C++ 的对象而言,其初始化的任务落在了构造函数(constructor)上。
    • 初始化不等于赋值:
      // 初始化后赋值(复制行为):
      GamePlayer::GamePlayer(char *pText, size_t slength, bool valid) { 
          this->pText = pText;
          this->slength = slength;
          this->valid = valid;
      }
      
      // 初始化:
      GamePlayer::GamePlayer(char *pText, size_t slength, bool valid) : pText(pText), slength(slength), valid(valid) {
          //do nothing
      }
      
    • 要记得总是在初值列中列出所有成员变量。
    • C++ 有十分固定的成员初始化顺序(父类先于子类,类的内部以成员声明次序初始化)。
  • 为了免除跨编译单元的初始化次序问题,用本地的 static 对象来替代非本地(non-local)的 static 对象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值