//---------------------------15/04/09----------------------------

//#26   尽可能延后变量定义式的出现时间

{

/*  1:只要你定义了一个变量而其类型带有一个构造函数或析构函数,即使变量没有被使用

还是要承担构造或析构的成本。为了避免这种情况,应该尽可能延后变量定义式的出现

2:再一次重复条款4:直接给定一个初值来让对象初始化比先构造一个对象,再赋值效率要高。

3:对于循环的情况:

1>当赋值成本低于一组构造+析构成本时,可以把对象定义在循环外面。

2>反之,把对象定义在循环体内部。

3>效率相当时,应该把对象定义在循环体内部。

*/

}

//#27   尽量少做转型动作

{

/*  1:尽量使用C++的新式转型:

1>const_cast:

通常被用来讲对象的常量性去掉,它是唯一有此功能的转型操作符。

2>dynamic_cast:

执行安全向下转型,但是要耗费大量成本。

3>reinterpret_cast

参数必须是指针,只是转化类型,并不转化内部结构。

想比较于static_cast,static_cast在基类到子类转型时会计算偏移值,而

reinterpret_cast不会,所以这个转型很危险,尽量别用。

4>static_cast

除了去除const属性外,其他转型都行。

2:在类中不要对*this进行转型                                       */

class Window

{

public:

virtual
void onResize(){...}

...

};

class SpecialWindow:public Window

{

virtual
void onResize()

{

static_cast<Window>(*this).onResize();

}

};

/*    上面这样调用的是转型时产生的副本(一个derived临时对象)的
base部分的那个函数。

所以不应该这么调用,而是使用Window::onResize();

3:dynamic_cast转型太慢了,能不用就不用,可以用两个方法避免这个转型:

1>直接使用derived类型的指针

2>在基类中定义一个无操作的virtual函数。

*/

}

//#28   避免返回handles指向对象内部成分

{

/*  1:如果返回一个handles(包括指针,引用,迭代器)指向对象内的private成员变量,那么外部就可以直接

修改这个成员变量了。虽然编译没错,但是这样就没有封装性可言了。

2:这带给我们两个教训:

1>成员变量的封装性最多只等于“返回其handles”的函数的访问级别。如果这个函数是public的

那么这个成员变量就是public的。

2>如果const成员函数传出一个handle,handle所指的数据与对象自身有关"private"或"protected"

而handle又被存储在对象之外,那么这个函数的调用者可以修改上面所指的数据。这是不合理的!!!

3:解决办法:

使返回指针和引用都是const就行了。

引用方式:                                                               */

const Point& upperLeft()
const { return pData->ulhc;}

//      指针方式:

const Point * upperLeft()
const { return pData;}

/*  4:返回一个handle代表对象内部成分总是危险的,这是因为:

handle被传出去就有可能产生 handle比它所指对象生命周期更长。

也就是handle很有可能在某时刻指向不存在的资源:                                  */

GUIObject* pgo;

...

const Point* pUpperLeft = &(boundingBox(*pgo).upperLeft());

//  这里只产生了一个临时对象,所以这条语句结束后就销毁了,而pUpperLeft也指向了已经销毁的对象资源

//  所以能避免返回handlers就避免吧。

}

//#29   为“异常安全”而努力是值得的

{

/* 1:“异常安全”有两个条件:

1>不泄漏任何资源。

解决办法是使用#13的办法,用对象(智能指针)来管理资源。

2>不允许数据败坏

2:异常安全函数提供三种保证之一:

1>基本承诺:如果异常被抛出,程序内的任何事物扔然保持在有效状态下。没有任何对象或数据结构会

因此而败坏,所有对象都处于一种内部前后一致的状态。然而程序的现实状态不可预料。

2>强烈保证:如果异常被抛出,程序状态不改变。调用这样的函数可以有这样的认知:如果函数成功,

就是完全成功,如果函数失败,程序会回到“调用函数前的状态”。

3>不抛掷(nothrow)保证:承诺绝不抛出异常。

3:我们的抉择:

1>有可能的话,提供nothrow保证。

大部分情况:

2>尽可能提供强烈保证,这里有一个好策略,不要为了表示某件事将要发生而改变对象状态,除非那件

事情已经发生了。

有一个好的策略会导致强烈保证:copy and swap。要做的事情就是:

1)先为要打算修改的对象copy一个副本。

2)把要做的事情都在副本上完成。

3)交换原对象和副本。

这里swap函数必须要能保证不抛出异常。

这个策略并不能保证整个函数有强烈的异常安全性。因为:

1)除了copy and swap外,如果还调用了其他函数,那么除非其他函数提供强烈异常保证

以上保证,不然就很难让整个函数提高强烈异常保证了。

2)即使其他函数提供了强烈异常保证,情况还是没有好转,因为其中一个函数改变了程序状态后

另外一个函数抛出了异常。

还有一件事会妨碍你提供强烈异常保证--效率问题,copy and swap带来的是一个对象的复制,

有时会消耗你无法承受的时间和空间。

3>当提供强烈保证不切实际时,就必须提供基本保证。

但是有时候可能你连基本保证都无法提供,是的。

如果你调用的函数原本不提供保证,那~~除非不调用,不然就没有任何保证了。。。。。

为了别人不会遇到同样的痛苦,你必须尽可能为你的函数提供异常保证。

*/

}

effective c++ 笔记 (26-29)的更多相关文章

  1. [Effective JavaScript 笔记]第29条:避免使用非标准的栈检查属性

    许多js环境都提供检查调用栈的功能.调用栈是指当前正在执行的活动函数链.在某些旧的宿主环境中,每个arguments对象含有两个额外的属性:arguments.callee和arguments.cal ...

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

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

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

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

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

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

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

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

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

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

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

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

  8. java effective 读书笔记

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

  9. JAVA自学笔记26

    JAVA自学笔记26 1.网络编程 1)用来实现网络互联的不同计算机上运行的程序可以进行数据交换 2)网络模型一般泛指 OSI:(Open System Interconnection)开放系统互联参 ...

  10. Effective STL 笔记 -- Item 6 ~ 7: Container and Object Pointer

    Effective STL 笔记 – Item 6 ~ 7: Container and Object Pointer 中间两次笔记被删掉了,简单补一下: Item 3 中提到如果将对象直接放入容器中 ...

随机推荐

  1. CISCO ASA 5505 经典配置案例

    nterface Vlan2 nameif outside  ----------------------------------------对端口命名外端口  security-level 0 -- ...

  2. python 3.6 的 venv 模块

    今天,在在使用 pycharm 的使用,进行创建 python的时候,发现使用默认的创建的选项使用的python 3环境 .而我系统默认的python环境是 python 2.7 环境:这就引起了我的 ...

  3. CVE-2013-2551

    目录 小白的CVE-2013-2551 分析 & 利用 0xFF 前言 0x00 环境和工具 0x01 分析POC POC 调试 0x02 利用 构造R3任意内存读写 劫持eip 利用利用 0 ...

  4. Windows 7 任务栏图标消失(变透明,仍然占有地方,但是点击无反应)的解决方法

    解决方案:清理资源管理器缓存(重启资源管理器) 1.打开程序管理器(ctrl+shift+esc) 2.在进程那里找到"explorer.exe",然后按结束进程 3.然后在文件( ...

  5. 一段刚刚出炉的CSV文件转换为DataTable对象的代码

    CSV是以文本形式保存的表格数据,具体是每列数据使用逗号分割,每行数据使用CRLF(\r\n)来结尾,如果数据值包含逗号或CRLF则使用双引号将数值包裹,如果数据值包含双引号则使用两个双引号做为转义. ...

  6. 【13】python time时间模块知识点备查

    表示时间的三种形式 # 时间模块 '''UTC(世界协调时间):格林尼治天文时间,世界标准时间,在中国来说是UTC+8DST(夏令时):是一种节约能源而人为规定时间制度,在夏季调快1个小时 时间的表示 ...

  7. PyQt5--ShowWindowCenter

    # -*- coding:utf-8 -*- ''' Created on Sep 13, 2018 @author: SaShuangYiBing ''' import sys from PyQt5 ...

  8. 《深入理解JVM》读书笔记

    目前只是整理了书的前几章,把jvm的内存划分简要说明.垃圾回收算法.垃圾回收器.常用的命令和工具进行说明.命令和工具的使用找个时间需要详细按步骤截图说明. 还有一部分内容是举例说明了一下字节码指令的样 ...

  9. BZOJ3236:[AHOI2013]作业(莫队,分块)

    Description Input Output Sample Input 3 4 1 2 2 1 2 1 3 1 2 1 1 1 3 1 3 2 3 2 3 Sample Output 2 2 1 ...

  10. 微信支付的notify.php中如何获取订单号(php版)

    不要直接使用demo中的notify.php,重写notify.php,继承WxPayNotify(可参考微信api),具体如下: require_once "WxPay.Api.php&q ...