一、基础议题

条款1:仔细区别pointers和references

  1. 指针使用*和->,引用使用“.”
  2. 引用必须指向一个已初始化的对象,不能为null,而指针可以指向某个对象,也可以为null
  3. 指针可以被重新赋值指向另一对象,而引用不可变更指向。

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

使用C++的转型操作符可以被很好的辨识,精确指明意图。

  1. static_cast:基本拥有与C旧式转型相同的威力,以及相同限制。几乎什么都可以转,但是不能将struct转int,double转指针,不能移除常量性。
  2. const_cast:用来将某个对象的常量性移除。
  3. dynamic_cast:用来执行继承体系中安全的向下转型或跨系转型。可以将指向基类对象的指针或引用转型为指向派生类的指针或引用。如果转型失败,对于指针返回null,对引用返回异常。
  4. reinterpret_cast:转换结果与编译器息息相关,所以不具备移植性。常用来转换函数指针类型,比如一个函数接受void*的函数指针,你可以把返回值为int类型的函数,转化为void*函数指针放进去调用。

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

派生类通常比其基类对象有更多的数据成员,两者大小不同,而数组内存的计算是以sizeof(数组中的对象)计算的,所以给基类传递派生类类型的数组,会导致数组大小不一致而出现未知错误。

条款4:非必要不提供default constructor

一个类如果缺乏default constructor将会带来:

  1. 产生数组时,一般而言没有任何方法为数组对象指定constructor自变量。
  2. 将不适用于template-based container classes,对模板来说,被实例化的目标类型必须要有default constructor。

二、操作符

条款5:对定制的“类型转换函数:保持警觉

有两种函数允许编译器进行转换:单参数构造函数(single-argument constructors)和隐式类型转换运算符。单参数构造函数是指只用一个参数即可调用的构造函数。该函数可以是只定义了一个参数,也可以是虽定义了多个参数但第一个参数以后的所有参数都有缺省值。

隐式类型转换运算符只是一个成员函数:operator关键字,其后跟一个类型符号。

1.explicit关键字是为了解决隐式类型转换而特别引入的。构造函数前用explicit声明,防止隐式转换。

2.定义类似功能的函数,而抛弃隐式类型转换,使得类型转换必须显示调用。例如 String类没有定义对Char*的隐式转换,而是用c_str函数来实施这个转换。

条款6:区别increment/decrement操作符的前置和后置形式

前置式和后置式操作符的实现(++)

后置operator++(int) 的叠加是不允许的,如i++++。

原因有两个:

一是与内建类型行为不一致(内建类型支持前置叠加);

二是其效果跟调用一次 operator++(int) 效果一样,这是违反直觉的。另外,后置式操作符使用 operator++(int),参数的唯一目的只是为了区别前置式和后置式而已,当函数被调用时,编译器传递一个0作为int参数的值传递给该函数。

防止后置式叠加的实现:通过返回const对象。

注:处置用户定制类型时,尽可能使用前置式,因为后置式会产生一个临时对象。

条款7:千万不要重载&&,||和,操作符

char *p = NULL;

if(p != 0 && strlen(p) > 10) { }

上面的代码不会报错,虽然 p 是空指针,但 && 符号采用"骤死式"评估方式,如果 pi == 0 的话,不会执行后面的语句。执行顺序从左到右。如果重载了&&这些操作符,会破坏"骤死式"评估方式,事先需要对两个参数都进行评估,并且未明确定义调用动作中的各参数评估顺序。

逗号操作符情况类似,比如f:

for(int i = 0, j = strlen(s) – 1; i < j; ++i, --j)

编译器首先评估逗号左侧,然后评估右侧,最后整个逗号表达式的结果以逗号右侧的值为代表。

不能重载:

.              .*              ::             ?:

new          delete        sizeof      typeid

static_cast  dynamic_cast  const_cast  reinterpret_cast

你能重载:

operator new        operator delete

operator   new[]    operator delete[]

+    -   *   /   %   ^     &   |     ~

!    =   <   >  +=   -=   *=   /=   %=

^=  &=  |=  <<  >>   >>=  <<=  ==   !=

<=  >=  &&  ||  ++   --    ,   ->*  ->

()  []

条款8:了解各种不同意义的new和delete

1. new operator 和operator new区别

string *ps = new string(“hello”);

new operator 第一用来发分配足够内存,放置某类型对象,第二它调用一个constructor为刚才分配的内存中的那个对象设初值。

Void * operator new(size_t size);

Operator new唯一任务是分配内存,可以被重写或重载,改变其行为。取operator new返回的内存并将之转换成一个对象是new operator的事。

2. placement new:特殊版本的operator new,可以在分配好的原始内存上构建对象。

注:如果你打算将对象产生于heap,使用new operator;如果只是分配内存,调用operator new;如果打算在heap object产生时自己决定内存分配方式,请写自己的operator new,并使用new operator;如果在已分配(并拥有指针)的内存中构造对象,使用placement new

3. delete operator 和operator delete

作用和区别于new一一对应,delete operator先析构对象,再释放内存,而operator delete只释放内存。

4. 数组anrray的内存分配方式

内存不再通过operator new分配,而是通过operator new[]分配,然后对数组中每个对象调用constructo。释放内存通过相应的operator delete[]。

More Effective C++笔记(一)(精心整理)的更多相关文章

  1. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  2. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  3. 2019年Unity学习资源指南[精心整理]

    前言 进入一个领域,最直接有效的方法就是,寻找相关综述性文章,首先你需要对你入门的领域有个概括性的了解,这些包括: 1.主流的学习社区与网站. 2.该领域的知名大牛与热心分享的从业者. 3.如何有效的 ...

  4. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  5. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  6. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  7. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  8. java effective 读书笔记

    java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...

  9. CSS精心整理的面试题

    CSS精心整理的面试题 1.设置边框的样式用border-style实现,设置边框的颜色用border-color实现 2.CSS的语法由选择器.属性.值三部分组成 3.设置一个div的最小宽度为50 ...

  10. Git使用方法(精心整理,绝对够用)转载

    Git使用方法(精心整理,绝对够用)   一.git客户端(本地仓库)的一些操作 1.设置账户(需要和github账户设置一致) git config --global user.name xxx g ...

随机推荐

  1. 常见JS

    1.获取当前月份第一天 var date = new Date(); var year = date.getFullYear(); var month = date.getMonth() + 1; v ...

  2. String(char[] value, boolean share) {

    记录一下今天被蠢到 1. 在观察StringBuffer类的toString方法时,发现了个没见过的方法 return new String(toStringCache, true); @Overri ...

  3. Springboot实现VNC的反向代理

    背景 ​ 用户需要通过前端HTML页面的noVNC(noVNC是什么?)客户端连接底层VNC Server服务端,为了防止VNC Server的IP暴露,因此需要做一层代理.正常情况下使用Nginx. ...

  4. C++学习 3 结构体

    结构体基本概念: 结构体属于用户自定义的数据类型,允许用户存储不同的数据类型: 结构体定义和使用: 语法:struct 结构体名 { 结构体成员列表 }: 通过结构体创建变量名的方式有三种:     ...

  5. .Net Core 获取上下文HttpContext

    1.先定义一个类 using Microsoft.AspNetCore.Http; namespace BCode.Util { public class MvcContext { public st ...

  6. CVE-2017-11882 漏洞分析总结 新手漏洞分析详细教程

    CVE-2017-11882分析总结 注: 这篇随笔记录了CVE-2017-11882漏洞分析的整个过程,并介绍了相关调试软件的使用 漏洞信息 CVE-2017-11882属于缓冲区溢出类型漏洞,产生 ...

  7. Shell 编程 基础用法

    Shell 编程 更改shell脚本权限 chmod u+x shell.sh 标准头部写法 #! /bin/bash #! /bin/dash 变量使用 a=10 print $a 读取命令行参数 ...

  8. 性能利器 Takin 来了!首个生产环境全链路压测平台正式开源

    6 月 25 日,国内知名的系统高可用专家数列科技宣布开源旗下核心产品能力,对外开放生产全链路压测平台产品的源代码,并正式命名为 Takin. 目前中国人寿.顺丰科技.希音.中通快递.中国移动.永辉超 ...

  9. Convolutional Neural Network-week2编程题1(Keras tutorial - 笑脸识别)

    本次我们将: 学习到一个高级的神经网络的框架,能够运行在包括TensorFlow和CNTK的几个较低级别的框架之上的框架. 看看如何在几个小时内建立一个深入的学习算法. 为什么我们要使用Keras框架 ...

  10. Noip模拟80 2021.10.18

    预计得分:5 实际得分:140?????????????? T1 邻面合并 我考场上没切掉的大水题....(证明我旁边的cty切掉了,并觉得很水) 然而贪心拿了六十,离谱,成功做到上一篇博客说的有勇气 ...