一、基础议题

条款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. 阿里云ECS服务器Centos中安装SQL Server(破解内存限制)

    前言 前段时间赶上阿里云618活动入手了一个低配的Linux服务器,供自己学习使用,在安装SQL Server中遇到了很多小问题,查阅很多博客结合自身遇到的问题做个总结. 安装过程 1.下载阿里云在线 ...

  2. Sentry 监控 - Distributed Tracing 分布式跟踪

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  3. docker采用registry部署简易仓库

    解释:registry部署简易仓库,实现免密上传拉取镜像(解决不在一个容器里,也能够实现镜像拉取成功) 1.安装启动registry服务 docker pull registry docker run ...

  4. react之组件生命周期

    四个阶段 初始化 运行中 销毁 错误处理(16.3以后) 初始化 constructor static getDerivedStateFromProps() componentWillMount() ...

  5. 题解 [HNOI2019]序列

    题目传送门 题目大意 给出一个\(n\)个数的数列\(A_{1,2,...,n}\),求出一个单调不减的数列\(B_{1,2,...,n}\),使得\(\sum_{i=1}^{n}(A_i-B_i)^ ...

  6. 洛谷2093 JZPFAR + KD-Tree学习笔记 (KD-Tree)

    KD-Tree这玩意还真的是有趣啊.... (基本完全不理解) 只能谈一点自己的对KD-Tree的了解了. 首先这个玩意就是个暴力... 他的结构有点类似二叉搜索树 每一层都是以一个维度作为划分标准. ...

  7. 关于 我的博客和Git-hub

    欢迎大家到我的GitHub 热烈讨论 https://github.com/ljj-19951010 由于另一个博客忘了怎么登陆了,换用此博客(仅供个人学习使用,请勿传播) 如果想看 特别详细的教程请 ...

  8. 【数据结构与算法Python版学习笔记】树——二叉查找树 Binary Search Tree

    二叉搜索树,它是映射的另一种实现 映射抽象数据类型前面两种实现,它们分别是列表二分搜索和散列表. 操作 Map()新建一个空的映射. put(key, val)往映射中加入一个新的键-值对.如果键已经 ...

  9. 如何从一台OPC Server访问多个PLC

    项目中遇到如下情况: 1. 整条生产线由多个PLC分别控制,但是所有PLC在同一个局域网内.PLC采用西门子的S7-200 Smart 2. 客户希望在操作工站的电脑(跟PLC在同一个局域网内)上提供 ...

  10. 5.29日 Scrum Metting

    日期:2021年5月29日 会议主要内容概述:人员调整,xyl同时兼顾前后端:确定表格缩放策略和新图表添加:强调任务分配,总结工作. 一.进度情况## 组员 负责 两日内已完成的工作 后两日计划完成的 ...