读书笔记五

  • 尽可能的延后变量定义式出现的时间

    •   产生问题:定义一个变量,其含有构造函数和析构函数。那么当代码运行到它的时候,就必须会产生构造成本和析构成本,如果这个变量最终未使用,那么就是浪费了资源空间,所以应该尽可能的延后变量定义式的时间
    •   解决方法:不只是应该延后变量的定义,知道非得使用该变量的前一刻为止,甚至应该尝试延后这份定义知道能够给他初值实参为止。这样可以避免构造析构函数和默认构造函数
    •   对于循环体中的变量:一般定义在循环体外部所需要的开销要少的多,不是定义在循环体中的局部变量
  • 尽量少做转型动作
    •   C++的四种转型手法:http://www.cnblogs.com/jerry19880126/archive/2012/08/14/2638192.html
    •   如果可以尽量避免转型特别是在注重效率的代码中避免dynamic_casts,如果有个动作需要转型,试着写一个无需转型的动作代替
    •   如果非得转型,试着将它藏在某个函数之后,客户可以随后调整该函数,而不是必须的将它放在代码中
    •   宁可使用新型的转型方式也不要去使用旧的转型方式
  • 避免返回handles指向对象内部成分
    •   问题产生:

      class point{
          point(int x,int y);
          ...
          void setx(int newval);
          void sety(int newval);
      };
      struct rectdata{
          point u;
          point l;
      };
      class rectangle{
      public:
          point & upperleft()const{return pdata->u;}
          point & upperright()const{return pdata->l;}
      private:
          std::str1::shared_ptr<rectdata> pdata;
      };
      int main()
      {
          point coord1(0,0);
          point coord2(100,100);
          const rectangle rec(coord1,coord2);
          rec.upperleft().sety(50);
      }
      这里我们能够通过最后的这个函数去修改private成员的值,那么私有成员变量就不是私有的了而是public的。
      最根本的原因是由于upperleft函数返回的是一个reference 指向rectangle对象的,所以私有变量就不是私有的了,失去了安全性和封装性

    •   reference,指针,迭代器都是handles中的一类,都是用来取得某个对象的一种工具,而返回代表一个内部对象的handles,他们很有可能修改成员变量和const成员函数,降低了类的封装性
      •   解决方法:让函数加上const,这样就不能修改值,只能读取值了。

        const point & upperleft()const{return pdata->u;}
            const point & upperright()const{return pdata->l;}

        但是这又会产生一个新的问题,就是point&返回的对象可能发生它所指的东西不存在了。这个例子感觉比价深啊。详见书P126

    •   避免返回handles(包括reference,指针,迭代器)指向对象内部。可以增加封装性,帮助const成员函数的行为像个const,并发生虚掉号码牌的可能性降至最低。
  • 为异常安全努力是值得的
    •   问题的产生

      class prettymenu{
      public:
          void changebackground(std::instream & imgsrc);
      private:
          Mutex mutex;
          Image *bgimage;
          int imagechanges;
      };
      void prettymenu::changebackground(std::istream&imgsrc){
          lock(&mutex);
          delete bgimage;
          ++imagechanges;
          bgimage=new image(imgsrc);//这个异常会导致unlock无法调用,资源泄漏;new异常原互斥器没有解锁,然而imagechanges还是++了,但是并没有一个新的image产生,数据被破坏了
          unlock(&mutex);
      }
      //这个例子没有遵守异常安全的两个条件
      //①不泄露任何的资源,②不允许数据的破坏//unlock的资源泄漏问题可以很容易解决:利用lock class类就能解决,所以把最后一句删除即可。
    •   解决方法:
      •   异常安全提供三个保证:

        •   强烈保证:如果异常被抛出了,程序中的所有东西仍然保持有效状态,任何数据结构或者对象会被破坏,抛出异常前后并没有发生变化。
        •   基本保证:异常抛出,程序状态不改变。函数成功,就是完全成功,函数失败,程序回复到调用函数之前的状态。
        •   承诺绝不抛出异常,总是能够完成要承诺完成的事情。
      •   一般而言,只能够做到第一条和第二条。一个好的操作方法是:pimpl idiom方法:copy and swap,将所有隶属对象的数据从原对象放进另一个对象内,然后赋予原对象一个指针,指向那个所谓的实现对象(副本)。实现所有操作后在进行swap,这个提供的是强烈保证

        struct PMImpl{
            std::tr1::shared_ptr<image> bgimage;
            int imagechanges;
        };
        class prettymenu{
        public:
            void changebackground(std::instream & imgsrc);
        private:
            Mutex mutex;
            std::tr1::shared_ptr<PMImpl> pimpl;//防止内存泄漏
        };
        void prettymenu::changebackground(std::istream&imgsrc){
            lock m1(&mutex);//获得mutex的副本数据
            str::tr1::shared_ptr<PMImpl> pnew(new PMImpl(*pimpl));//
            pnew->bgimage.reset(new image(imgsrc));//修改副本
            ++pnew->imagechanges;
        
            swap(pimpl,pnew);//置换数据,释放mutex
        }
      •   让函数具备异常安全性的方法步骤:①以对象管理资源:防止内存泄漏。②挑选三个异常安全保证中的一个实施与函数中,保证异常安全性,选择上应该选择第二个。
  • 透彻了解inlining的里里外外(内联函数)
    •   inline函数的表示

      •   隐式的:声明在类体内部,有些friend也可以是inline函数

        class person{
        public:
            int age()const{return theage;}
        private:
            int theage;
        };
      •   显示的,在函数前面加上inline关键字
    •   inline函数通常都是置于头文件中的,在编译过程中进行inlining,必须知道函数本体长什么样子,才能将函数所有本体代码替换执行的inline函数。所以inlining一般都是编译期的行为。
    •   由于inline是在编译期执行的,而虚函数时在运行的时候才将该函数具体化执行的。所以凡是虚函数一般都不是inline函数。所以,一个表面上看起来inline‘的函数是否真的inline,取决于环境,主要屈居于编译器。如果无法inline,会发出一个警告信息。
    •   class类中的构造函数和析构函数一般是不能使用inline的,因为成本开销可能非常的大,但是表面上看不到它的开销,所以不适合使用。
    •   将大多数inlining限制在小型的,频繁调用的函数上。不要只因为function出现在头文件,就将他们声明为inline。
  • 将文件间的编译依存关系降至最低
    •   

时间: 2024-11-08 13:30:55

读书笔记五的相关文章

《算法导论》读书笔记(五)

摘要: 本章介绍了二叉查找树的概念及操作.主要内容包括二叉查找树的性质,如何在二叉查找树中查找最大值.最小值和给定的值,如何找出某一个元素的前驱和后继,如何在二叉查找树中进行插入和删除操作.在二叉查找树上执行这些基本操作的时间与树的高度成正比,一棵随机构造的二叉查找树的期望高度为O(lgn),从而基本动态集合的操作平均时间为θ(lgn). 1.二叉查找树 二叉查找树是按照二叉树结构来组织的,因此可以用二叉链表结构表示.二叉查找树中的关键字的存储方式满足的特征是:设x为二叉查找树中的一个结点.如果

《启示录》读书笔记五

1.敏捷开发 敏捷开发以用户的需求进化为核心,采用迭代.循序渐进的方法进行软件开发.在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视.可集成和可运行使用的特征.换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态. 2.瀑布式开发 瀑布模型式是最典型的预见性的方法,严格遵循预先计划的需求.分析.设计.编码.测试的步骤顺序进行.步骤成果作为衡量进度的方法,例如需求规格,设计文档,测试计划和代码审阅等等

悟道—位IT高管20年的职场心经(读书笔记五)

悟道--一位IT高管20年的职场心经 第五章 搞定老板 "老板就是老板" 这一点,你可能会忘了,他一定不会忘: "老板不会总是老板" 这一点,他可能会忘,你最好别忘. 1.1  谁是老板 老板手上有的权力,你应该尊重.权力,意味着资源. 1.2  三招搞定老板 尊重老板由于他毕竟是你的老板: 把老板当客户,善用老板的资源! 老板的资源:权力.能力.经验.信息. 1.3  请示的学问:该不该请示 和自己的老板沟通,理解老板的性格特点,然后做事. 1.4  请示的学问:

Android驱动开发读书笔记五

第五章 本章介绍了S3C6410开发板的功能,开发板的不同主要是在烧录嵌入式系统的方式不同,以及如何在此开发板上安装Android. 1.安装串口调试工具minicom 首先需要一根USB转串口线,由于安装的是Ubuntu Linux所以需要按照以下步骤.配置和测试minicom (1).检测当前系统是否支持USB转串口 命令lsmod  | grep usbserial (2)安装minnicom apt-get install minicom (3)配置minicom minicom -s,

机器学习实战读书笔记(五)Logistic回归

Logistic回归的一般过程 1.收集数据:采用任意方法收集 2.准备数据:由于需要进行距离计算,因此要求数据类型为数值型.另外,结构化数据格式则最佳 3.分析数据:采用任意方法对数据进行分析 4.训练算法:大部分时间将用于训练,训练的目的是为了找到最佳的分类回归系数 5.测试算法:一旦训练步骤完成,分类将会很快. 6.使用算法:首 先,我们需要输入一些数据,并将其转换成对应的结构化数值:接着,基于训练好的回归系数就可以对这些数值进行简单回归计算,判定它们属于哪个类别:在这之后,我们就可以在输

R语言实战读书笔记(五)高级数据管理

5.2.1 数据函数 abs: sqrt: ceiling:求不小于x的最小整数 floor:求不大于x的最大整数 trunc:向0的方向截取x中的整数部分 round:将x舍入为指定位的小数 signif:舍入为指定的有效数字位数 cos,sin,tan acos,asin,atan:反正弦,反余弦,反正切 cosh,sinh,tanh:双曲余弦,双曲正弦和双曲正切 acosh,asinh,atanh:反双曲余弦,反双曲正弦和反双曲正切 log(x,n):以n为底 log: log10: ex

锋利的jQuery--编写jQuery插件(读书笔记五)[完结篇]

1.表单验证插件Validation   2.表单插件Form 3.动态事件绑定插件livequery 可以为后来的元素绑定事件 类似于jQuery中的live()方法 4.jQuery UI   5.jQuery Cookie   6.遮罩层插件:thickbox 7.编写jQuery插件 <1>编写插件的目的:给已经有的一些列方法或函数做一个封装,一遍在其他地方使用,方便后期维护和提高开发效率. <2>三种类型的插件 a:封装对象方法的插件 jQuery.fn.extend()

《Distributed Programming With Ruby》读书笔记五 RingyDingy (Part2 chapter3)

Part II Third-Party Frameworks and Libraries The first part of this book takes a deep dive into two main libraries: DRb and Rinda Chapter3: RingyDingy Including 6 parts: Installation Getting Started with RingyDingy "Hello World" the RingDingy Wa

《Android深度探索卷一》读书笔记五

下载和编译Linux内核源代码 Android源代码不包含Linux源代码,必须单独下载.不能直接在www.kernel.org下载Linux内核,应在Google提供的网站下载Android中使用的Linux内核. 1.下载“git clone https://android.googlesource.com/kernel/common.git”,进入common目录,“git branch -a”查看当前有的远程版本,之后导出 到导出所需版本“git checkout -b android-

Oracle事务原理探究1--oracle核心技术读书笔记五

1. 冲突解决 假如有一个系统只有你和我两个用户,并且我们都在持续对系统中一小部分数据做修改和查询操作. 如果你正在数据库中做一批修改操作,而我正在做查询,我一定不能看到你所做的修改,直到你告诉我可以看到你所做的所有更改才行(你提交了事务).因此在oracle内部,必须有一个高效的办法来识别哪些数据我可以看到,哪些数据我不可以看到. 从相反的角度来看,在你提交事务的时候,你需要一种高效的机制让其他所有人能够看到事务已经提交(也就是要告诉别人你所有修改过的数据都是可见的了).更极端一点的情况是,你