博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
###《More Effective C++》- 基础议题
阅读量:5323 次
发布时间:2019-06-14

本文共 3323 字,大约阅读时间需要 11 分钟。

More Effective C++

#@author:       gr#@date:         2015-05-11#@email:        forgerui@gmail.com

一、仔细区别pointers和references

1.1. 初始化

指针可以不初始化,引用必须初始化为。

引用没有null reference,指针可以设为NULL.

//指针初始化为0,NULL,nullptrchar *str = 0;int a = 1;//引用必须初始化,int &b;是错误的int &b = a;

1.2. 效率

因为不存在null reference,引用使用前不需要测试其有效性,效率比指针高一些。

void print(const double& rd){    cout << rd;     //不需要测试有效性}void print(const double* rd){    if (*rd)        cout << rd;     //需要测试是否为空}

1.3. 指向

指针可以改变指向的对象,而reference始终指向最终指向的对象。

string s1("aaa");string s2("bbb");string& rs = s1;string *ps = &s2;rs = s2;            //不变,仍指向s1,但s1值改变了ps = &s1;           //改变,改为指向s1

在不同时间指向不同对象,使用指针;一旦代表了该对象就不能够改变,这时使用reference。比如operator[]操作符,应该使用引用;如果返回指针在赋值时需要写成下面的样子,很不直观,容易产生误解:

vector
a(10);a[5] = 2; //使用引用*a[5] = 2; //使用指针

二、最好使用C++转型操作符

2.1. 新式转型

static_cast
(expression) //最常用的转型const_cast
(expression) //将常量性去掉dynamic_cast
(expression) //继承转换,将父类转为子类,无法转换,返回null或摄氏reinterpret_cast
(expression) //与编译平台有关,不具移植性

2.2. reinterpret_cast

typedef void (*FuncPtr)();FuncPtr funcPtrArray[10];int doSomething();          //将doSomething放funcPtrArray中funcPtrArray[0] = &doSomething;     //错误,类型不符,无法存放funcPtrArray[0] = reinterpret_cast
(&doSomething);

2.3. 先用旧式取代新式,方便升级

#define static_cast(TYPE, EXPRESSION) ((TYPE) (EXPRESSION))#define const_cast(TYPE, EXPRESSION) ((TYPE) (EXPRESSION))

虽然,新式转型又长又臭,但使用新式转型更加清晰,也会让你尽量减少转型的使用。

三、绝对不要以多态(Polymorphism)方式处理数组

3.1. 多态数组存在的问题

class BST{...};class BalancedBST : public BST{...};void printBSTArray(ostream& s, const BST array[], int numElements){    for (int i = 0; i < numElements; ++i)    {        s << array[i];    }}BST BSTArray[10];printBSTArray(cout, BSTArray, 10);      //表现良好BalancedBST bBSTArray[10];printBSTArray(cout, bBSTArray, 10);     //传入子类,存在问题

如果想对子类的数组进行多态处理,往往因为子类的大小被解析成父类的大小,而无法达到想要的结果。这样会产生不可预测的结果。

同样在进行数组删除时,同样也会遇到这样的问题,所以数组和多态不要一起使用

牢记条款33所说“具体类不要继承自另一个具体类”可以避免这个错误。

四、非必要不提供default constructors

4.1. 无中生有

有些类可以“无中生有”产生,然而有些类无法“无中生有”,因为这种产生的对象毫无意义。如:一个通信簿字段的class,如果没有获得外界指定的人名,产生出来的对象将毫无意义。这些对象不应该提供default constructor

4.2. 缺乏default constructor带来的问题

如下面的EquipmentPiece,它没有默认的构造函数,它将产生一些问题。

class EquipmentPiece{public:    EquipmentPiece(int IDNumber);           //因为定义了其它ctors,所以编译器不会再生成defalut ctors};
  1. 在定义数组时,无法产生一个类型数组

    EquipmentPiece bestPiece[10];           //错误,无法调用EquipmentPiece ctors EquipmentPiece *bestPieces = new EquipmentPiece[10];        //错误

    解决这个问题方法是使用“指针数组”而非“对象数组”:

    typedef EquipmentPiece* PEP; PEP bestPiece[10];                      //很好,定义10个元素的指针数组 PEP *bestPieces = new PEP[10];      //也很好 for (int i = 0; i < 10; ++i)     bestPieces[i] = new EquipmentPiece( ID Number );
  2. 它们不适用于许多template-based container classes,这些contrainer希望实例化的目标得有一个default constructors

    template 
    class Array{ public: Array (int size); private: T *data; }; template
    Array
    ::Array(int size) { data = new T[size]; //会报错,需要调用default ctors }

    解决方法是谨慎设计template,消除对default ctors的需求。比如vector就不要求默认构造函数。

  3. virtual base classes时存在问题

    可能要求所有派生类都要提供virtual base classconstructors自变量。

4.3. 提供默认构造函数存在的问题

  1. 其它成员需要检查ID是否存在,使其它member function变得复杂。
  2. 影响class的效率。

转载于:https://www.cnblogs.com/gr-nick/p/4563658.html

你可能感兴趣的文章
求1+2+…+n
查看>>
开发者必备的6款源码搜索引擎
查看>>
一个值只有0和1的字段,到底要不要建索引?
查看>>
JavaScript的Math对象
查看>>
form 禁止跳转
查看>>
第七周学习总结
查看>>
20145122《JAVA开发环境的熟悉》实验报告
查看>>
186. Reverse Words in a String II
查看>>
JAVA-初步认识-第五章-数组-常见操作-进制转换整合
查看>>
如何在.net4.0中使用.net4.5的async/await
查看>>
Spring自定义标签实现及踩过的坑(亲测)
查看>>
一些字符串的题
查看>>
第2章:标准输入与输出
查看>>
个人项目——买书
查看>>
POJ 2309 BST
查看>>
Codefroces 415B Mashmokh and Tokens
查看>>
HDU 3440 House Man
查看>>
Mysql 用户管理
查看>>
实验五
查看>>
焊接贴片
查看>>