条款1:区别指针和引用

条款2:最好使用C++转换操作符

条款3: 绝对不要以多态的方式处理数组

条款4: 避免无用的缺省构造函数


条款1:区别指针和引用

1.指针(pointer) 使用[*/->]

 引用(reference) 使用[.]

2.a.引用没有null

b.引用必须初始化

 c.引用不可以被重新赋值

3.引用比指针的效率更高(其实只是更安全),引用不需要判定是否为null

总结: 指向不变用引用


条款2:最好使用C++转换操作符

C的强制转换是一定会实现,但是并不保证强转后的结果是否正确.而且可读性差.C++封装了这C的强转并且提高了强转的安全性.

下面简单介绍一下C++的四种强制转换

1.static_cast 用于普通类型的转换(int,char...) [类似于 int const *p 不可以用static_cast<>]

2.const_cast 去除const属性 [eg:const char *pc=" HDU"; char *p=const_cast<char *>(pc);]

3.dynamic_cast 多态之间类型转换 转换指针失败时返回null

                 转换引用失败时抛出bad_cast

                 转换类型失败时返回 0

4.reinterpret_cast 指针类型间的转换


条款3: 绝对不要以多态的方式处理数组

class Base{ ... };(size: 4)// 假设大小为4

class Driver: public BASE{ ... };(size: 6)//子类一般会比父类多一些data 所以一般的子类都会比父类大一些

void printArray(ostream& s,const Base array[],int numElements){

{

  for (int i = 0; i < numElements; ) {

  s << array[i]; 

  }

}

如果用 Base BaseArray[10] 调用该函数 会正常运行

如果用 Driver DriverArray[10] 去调用该函数 会通过编译 但是后果却不可预估

我们仔细想一想 array[i]代表的意义是 *(array + i)  它的步长是 i*sizeof(数组中的对象) 在该函数 步长为4

BaseArray它的大小是4 可以正常调用此函数  然而DriverArray的步长是6  循环后会造成一种不可预估的错误


条款4: 避免无用的缺省构造函数

不提供默认构造函数是为了防止创建出无意义的类

 class Person{
public:
Person(int IDCard);
...
};

由于Person缺少默认构造函数,其运行时可能在3种情况下出错

1.创建数组时

 Person person[]; //错误无法调用正确的默认构造函数
 Person * person = new Person[];//错误 同上

解决方案:

a:

 int ID1,ID2,ID3,ID4...ID10
Person person[] = {
person(ID1),
person(ID2),
...
Person()}// 使用non-heap数组 缺点:无法延伸至heap数组 创建1000个需初始化1000次

b:

 tepedef Person * p;// p是指向Person的一个指针
p array[];
p * array = new p[];
for (int i =; i<;i++)
{
p[i] = new Person[IDCard];
}
//两个缺点手动删除指针,需创建容纳指针的内存,详情见条款8

c:

 void *rawMemory =operator new[](*sizeof(Person));
Person *person =static_cast<Person*>(rawMemory);
for (int i = ; i < ; ++i){
new (&person[i]) Person( IDCard);
}
//缺点需以构造顺序相反的顺序析构
for (int i = ; i >= ; --i){
person [i].~Person();
operator delete[](rawMemory);
}
//切记不能使用普通的数组删除法
//delete [] person ;//错误 person 不是new出来的

2.如果该类没有默认构造函数,那么它有可能不适用有些模板。如果类的设计者自定义的类模板(准确的说应该是容器模板)使用内存池的方法的话,这一个缺陷可以避免

3.如果虚基类没有默认构造函数,则每个派生类都必须调用虚基类的构造函数.这个是不被期待的.

MoreEffectiveC++Item35(基础议题)(条款1-4)的更多相关文章

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

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

  2. MoreEffectiveC++Item35(效率)(条款16-24)

    条款16 谨记80-20法则 条款17 考虑使用 lazy evaluation(缓释评估) 条款18 分期摊还预期的计算成本 条款19 了解临时对象的来源 条款20 协助完成"返回值的优化 ...

  3. MoreEffectiveC++Item35(操作符)(条款5-8)

    条款5 对定制的"类型转换函数"保持警惕 条款6 区别increment/decrement操作符的前值和后置形式 条款7 千万不要重载&&,||,和,操作符 条款 ...

  4. MoreEffectiveC++Item35 条款27: 要求或禁止对象产生于heap中

    一 要求对象产生在heap中 阻止对象产生产生在non-heap中最简单的方法是将其构造或析构函数声明在private下,用一个public的函数去调用起构造和析构函数 class UPNumber ...

  5. MoreEffectiveC++Item35(异常)(条款9-15)

    条款9 使用析构函数防止内存泄漏 条款10 在构造函数中防止内存泄漏 条款11 禁止异常信息传递到析构函数外 条款12 理解"抛出一个异常''与"传递一个参数"或调用一个 ...

  6. MoreEffectiveC++Item35 条款26: 限制某个class所能产生的对象个数

    一 允许零个或一个对象 我们知道每当即将产生一个对象,我们有一个constructor被调用,那么我们现在想组织某个对象的产生,最简单的方法就是将其构造函数声明成private(这样做同事防止了这个类 ...

  7. MoreEffectiveC++Item35 条款25 将constructor和non-member functions虚化

    1.virtual constructor 在语法上是不可将构造函数声明成虚函数,虚函数用于实现"因类型而异的行为",也就是根据指针或引用所绑定对象的动态类型而调用不同实体.现在所 ...

  8. ###《More Effective C++》- 基础议题

    More Effective C++ #@author: gr #@date: 2015-05-11 #@email: forgerui@gmail.com 一.仔细区别pointers和refere ...

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

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

随机推荐

  1. JS正则表达式从入门到入土(10)—— 字符串对象方法

    字符串对象方法 search方法 String.prototype.search(reg) search方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,方法返回第一个匹配结果的 ...

  2. 关于Linq的对List<实体>去掉重复ID的一个小例子!

    注意 下面的代码只要ID相同(即使其他的不相同)都会过滤掉,简单来讲就是过滤掉ID相同的实体,如果ID相同,其他属性取第一个的值 List<Abc> list = new List< ...

  3. 20145328 《Java程序设计》第6周学习总结

    20145328 <Java程序设计>第6周学习总结 教材学习内容总结 输入/输出 InputStream与OutputStream 从应用程序角度来看,如果要将数据从来源取出,可以使用输 ...

  4. LeetCode (226):Invert Binary Tree 递归实现

    Invert a binary tree. 4 / \ 2 7 / \ / \ 1 3 6 9 to 4 / \ 7 2 / \ / \ 9 6 3 1 Trivia:This problem was ...

  5. 彻底搞懂hashCode与equals的作用与区别及应当注意的细节

    以前写程序一直没有注意hashCode的作用,一般都是覆盖了equals,缺没有覆盖hashCode,现在发现这是埋下了很多潜在的Bug!今天就来说一说hashCode和equals的作用. 先来试想 ...

  6. HttpServletRequest request方法详解

    //1.获取请求参数 //获取参数的单个值,如有多个则只返回第一个 String parameter1 = request.getParameter("demo"); //获取参数 ...

  7. MySQL表类型MyISAM/InnoDB的区别(解决事务不回滚的问题)

    MyISAM:这个是默认类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法.与 ...

  8. js打乱数组的实战应用

    文章首发于: https://www.xiabingbao.com/post/javascript/js-random-array.html 在js中,能把数组随机打乱的方法有很多,每个方法都有自己的 ...

  9. HDU - 5988The 2016 ACM-ICPC Asia Qingdao Regional ContestG - Coding Contest 最小费用流

    很巧妙的建边方式 题意:有n个区域,每个区域有一些人数si和食物bi,区域之间有m条定向路径,每条路径有人数通过上限ci.路径之间铺了电线,每当有人通过路径时有pi的概率会触碰到电线,但是第一个通过的 ...

  10. IDEA运行时Information:java: Errors occurred while compiling module!

    在网上找了资源 说看一下项目JDK,字符编码UTF-8,但是都不很实用,突然发现: IDEA的右下角改变字符编码的按钮,先改成GBK然后再改成UTF-8,然后就OK了. 原因:导入开源的项目的时候,你 ...