您的位置:首页 > 编程语言 > C语言/C++

Effective C++随笔 1 to 4 让自己习惯C++

2019-07-26 20:25 561 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/lxx909546478/article/details/97389919
1.视C++为一个语言联邦
2.尽量以 const enum inline 代替 #define

即以编译器处理替代预处理
建议:(1)对于单纯常量,尽量用 const 与 enum 代替
(2)对于形似函数的宏,使用 inline 内联函数代替

3.尽可能使用 const

const适用范围:
(1)在class外部修饰global与namespace作用域中的常量。
(2)在class内部修饰static与非static变量。
(3)修饰指针

修饰效果在于const关键字与 * 的位置

const char* p="hello world";// const数据,非const指针
char const* p="hello world";// 同上
char* const p="hello world";// const指针,非const数据
const char* const p="hello world";// const指针,const数据

与之类似的是STL中的iterator,const关键字修饰iterator表明该迭代器不能指向其他的元素;若要使指向的元素不可被修改,应使用const_iterator。
(4)修饰函数的返回值与参数
  修饰参数的效果是显而易见的:
它将保证传入的参数(一般是传引用调用)在整个函数运行期间都不会被重新赋值。
  应当说明的是:
有时返回const对象是必要的,比如用户自定义重载后的操作符,可能会出现如下赋值:
a+b=c(常见于做判断时将==打成=)
  对于该错误应当返回一个异常,该异常应由重载的+返回的const限定给出,返回const对象保证该重载操作符返回一个不可修改的值,将对异常赋值操作抛出异常。
(5)修饰成员函数
  ·返回值是否是const可以构成函数重载
  使用const限定符修饰成员函数,是为了确认该成员函数可作用于const对象。
  它带来的两个好处:
  使class接口容易理解,标明了哪些函数可以修改对象内容,哪些不可以。
  使"操作const对象"成为可能。
  
  成员函数限定const后,常常会出现的问题是:由于bitwise const简单的用赋值来判定,函数内部不允许任何的赋值操作,此时若需要在const修饰的成员函数内部完成无伤大雅的赋值,则应当使用mutable关键字释放掉非静态成员的bitwise const约束。(事实上还有其他的解决方案,如:C++ Primer中给出了const_cast的方法,使用函数指针来做)
值得注意的是:由于返回值是否是const可以构成函数重载,常常会出现返回值为const与非const成员函数仅仅在返回值有不同,而内部代码完全相同的情况,这将导致我们不愿看到的代码冗余问题。
  为了避免代码冗余问题,我们有两种选择:
  使用非const调用const成员函数
  使用const调用非const成员函数
  我们将会看到,前者是更好的做法,因为后者在const修饰的成员函数调用了非const函数,const成员函数承诺绝不修改内部的值,但这一做法很明显违背了这一承诺,该函数内成员有被修改的风险。
  前者做法仅需要将返回的const对象转换为非const即可,我们使用const_cast机制消除返回值的const属性。示例如下:

4.确定对象在使用前已被初始化

值得关注的一点是:构造函数中的一系列赋初值操作并不是初始化操作,而是赋值操作。事实上成员变量的初始化发生在构造函数调用之前。因此我们通常采用初始化列表而非采用赋值实现初始化。
同时,一旦使用了初始化列表进行初始化操作,那我们就有必要将所有的成员变量都加入初始化列表。
我们也并不总是将初始化列表作为我们的第一选择,一个例外是:当一个类有多个构造函数,这些构造函数中都初始化相同的元素导致代码冗余。此时我们选用的做法是,将一些赋值与初始化做得一样好的成员变量放入一个函数进行赋值(通常该函数为private),在这些构造函数中调用该函数而非使用初始化列表完成初始化操作。
此条目下还有一个复杂的初始化次序的问题尚未解决,我们在此进行讨论:
应当指明的是,这里的初始化次序仅指不同编译单元内定义的 non-local static对象的初始化次序。
如在两个源码文件中,每一个源码文件中至少包含一个non-local static对象(也即该对象是global或者在namespace作用域内),其中一个对象的初始化使用了另一个对象,而此时另一对象可能尚未初始化(由于C++并未定义两个源码文件中的non-local static对象哪个先进行构造),这将违背该条目的准则。
解决方案:
将每个non-local static对象搬入自己专属的函数内(该对象在函数内被声明为static),该函数返回一个reference指向它所含的对象,而此后用户将使用这些函数而非直接使用对象来完成后续工作。这种方式即为设计模式中的Singleton模式的常见实现方法。
示例如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: