More Effective C++

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

一、仔细区别pointers和references

1.1. 初始化

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

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

//指针初始化为0,NULL,nullptr
char *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<int> a(10);
a[5] = 2; //使用引用
*a[5] = 2; //使用指针

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

2.1. 新式转型

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

2.2. reinterpret_cast

typedef void (*FuncPtr)();
FuncPtr funcPtrArray[10];
int doSomething(); //将doSomething放funcPtrArray中
funcPtrArray[0] = &doSomething; //错误,类型不符,无法存放
funcPtrArray[0] = reinterpret_cast<FuncPtr>(&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 <typename T>
    class Array{
    public:
    Array (int size);
    private:
    T *data;
    };
    template <typename T>
    Array<T>::Array(int size)
    {
    data = new T[size]; //会报错,需要调用default ctors
    }

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

  1. virtual base classes时存在问题

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

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

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

###《More Effective C++》- 基础议题的更多相关文章

  1. More Effective C++ 基础议题(条款1-4)总结

    More Effective C++ 基础议题(条款1-4)总结 条款1:仔细区别pointers和references 如果有一个变量,其目的是用来指向(代表)另一个对象,但是也有可能它不指向(代表 ...

  2. More Effective C++ - 章节一 : 基础议题

    1. 仔细区分 pointers 和 references references和pointers的差别描述如下: pointer:当需要考虑"不指向任何对象"时,或者是考虑&qu ...

  3. More Effective C++: 01基础议题

    01:仔细区别 pointers 和 references 1:没有所谓的null reference,但是可以将 pointer 设为null.由于 reference 一定得代表某个对象,C++ ...

  4. MoreEffectiveC++Item35(基础议题)(条款1-4)

    条款1:区别指针和引用 条款2:最好使用C++转换操作符 条款3: 绝对不要以多态的方式处理数组 条款4: 避免无用的缺省构造函数 条款1:区别指针和引用 1.指针(pointer) 使用[*/-&g ...

  5. C/C++ 随笔目录

    [1]基础部分 (1)宏定义 <assert> <offset宏> <#pragma once> <宏定义学习> <预处理语句> <# ...

  6. C++学习书籍推荐《More Effective C++》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <More Effective C++:35个改善编程与设计的有效方法(中文版)>:传世经典书丛 媒体推荐 <Effective c++&g ...

  7. More Effective C++ 35 条款

    一.基础议题(basics) 条款1:仔细区别 pointers 和 references(Distinguish between pointers and references) 一个基本的语法问题 ...

  8. More Effective C++笔记(一)(精心整理)

    一.基础议题 条款1:仔细区别pointers和references 指针使用*和->,引用使用"." 引用必须指向一个已初始化的对象,不能为null,而指针可以指向某个对象 ...

  9. 《More Effective C++》读书笔记(零)Basic 基础条款

    这是篇读书笔记,只记录自己的理解和总结,一般情况不对其举例子具体说明,因为那正是书本身做的事情,我的笔记作为梳理和复习之用,划重点.我推荐学C++的人都好好读一遍Effective C++ 系列,真是 ...

随机推荐

  1. [OC Foundation框架 - 5] NSString的常用方法

             NSString *s1 = ";   1.比较 使用 == 号比较的是字符串地址 NSString *s4 = @"abcdefg"; NSStrin ...

  2. .NET设计模式(5):工厂方法模式(Factory Method)

    ):工厂方法模式(Factory Method)    工厂方法模式(Factory Method) --.NET设计模式系列之五 Terrylee,2004年1月2日 转载:http://terry ...

  3. Sass 默认样式库

    Sass 默认初始化样式库 @charset "utf-8"; // 变量存储 // 字体Unicode编码 微软雅黑:\5FAE\8F6F\96C5\9ED1 , 宋体:\5B8 ...

  4. 从经典问题来看 Copy 方法(转)

    来自:Gua | 瓜地 链接:https://desgard.com/copy/  在初学 iOS 的时候,可能会被灌输这么一个常识,切记 NSString 的 property 的修饰变量要写作 c ...

  5. zabbix邮件报警脚本(Python)

    #!/usr/bin/python #coding:utf-8 import smtplib from email.mime.text import MIMEText import sys mail_ ...

  6. 【22】将成员变量声明为private

    1.为什么要将成员变量声明为private,语法一致性,只通过方法暴露接口. 2.使用方法,可以对成员变量更精确的控制.比如:为所有可能的实现提供弹性,不同实现可以替换:控制可读可写:验证约束条件:处 ...

  7. [JavaScript]'this'详解

    http://blog.csdn.net/sodino/article/details/51318565

  8. wcf自身作为宿主的一个小案例

    第一步:创建整个解决方案 service.interface:用于定义服务的契约(所有的类的接口)引用了wcf的核心程序集system.ServiceModel.dll service:用于定义服务类 ...

  9. com.ulitis.www

    package com.ulitis.www; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io ...

  10. Bleed Brake Master Cylinder with Intelligent Tester IT2

    When the brake fluid level drops too low in the master cylinder reservoir, air bubbles can get caugh ...