zoukankan      html  css  js  c++  java
  • effective c++ 笔记 (26-29)


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


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

    {

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

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

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

        3:对于循环的情况:

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

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

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

    */

    }


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

    {

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

            1>const_cast:

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

            2>dynamic_cast:

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

            3>reinterpret_cast

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

                想比较于static_caststatic_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成员函数传出一个handlehandle所指的数据与对象自身有关"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>当提供强烈保证不切实际时,就必须提供基本保证。

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

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

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

    */

      

    }




  • 相关阅读:
    第010讲~第011讲:一个打了激素的数组
    练习15--阅读文件
    第007讲~第009讲:了不起的分支和循环
    第006讲:Python之常用操作符
    第005讲:闲聊之python的数据类型
    练习14--提示和传递
    第004讲:改进我们的小游戏
    ICPC Central Europe Regional Contest 2019 H. Ponk Warshall
    2019 ICPC Asia Yinchuan Regional G. Pot!!(线段树 区间更新 区间查询)
    CF1286A Garland
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983135.html
Copyright © 2011-2022 走看看