<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    PS,1880后程序員

    看不完的牙,寫不完的程序,跑不完的步。
    隨筆 - 97, 文章 - 34, 評論 - 10, 引用 - 0
    數據加載中……

    C++ Primer 之 讀書筆記 第十三章

     

    Chapter 13. Copy Control

    13.1 The Copy Constructor

    首先,這真是一個有趣的命題。我老喜歡。這讓我想起的是Javaclone。(寫下這句話時我還沒有看這一節,只是一個預感)

    過癮啊。(寫下這句話時我剛剛讀完這一節,還沒有來得及整理筆記,理順思路)

    什么叫做拷貝構造函數?

    拷貝構造函數有一個形參,并且這個形參是指向同一個類的對象的引用。(The constructor that takes a single parameter that is a (usually const) reference to an object of the class type itself is called the copy constructor.

    對象定義的形式

    c++支持兩種形式的初始化:

    1.      直接初始化,使用初始化式(initializer),直接調用對應的構造函數。

    2.      拷貝初始化,使用’=’。先調用構造函數生成臨時對象,然后再調用拷貝構造函數把臨時對象拷貝到我們要創建的對象里。(Copy-initialization first uses the indicated constructor to create a temporary object. It then uses the copy constructor to copy that temporary into the one we are creating

    string null_book = "9-999-99999-9"; // copy-initialization

    string empty_direct;                // direct-initialization

    對于類的對象,當指定單一的實參或者為了拷貝明確構建臨時對象時,才能使用拷貝初始化。(For objects of class type, copy-initialization can be used only when specifying a single argument or when we explicitly build a temporary object to copy.

    ifstream file2 = "filename"; // error: copy constructor is private

    // This initialization is okay only if

    // the Sales_item(const string&) constructor is not explicit

    Sales_item item = string("9-999-99999-9");

    額外嘮嘮Sales_item item = string("9-999-99999-9");

    只有當Sales_item的構造函數中沒有把Sales_item(const string&)這個構造函數聲明為explicit時,這個初始化才正確。這其中包含了一個隱式的類型轉換:由實參string("9-999-99999-9");生成Sales_item類型的對象,然后再調用copy函數拷貝給item

    但是(咋這么多但是呢)如果這么寫Sales_item item2 = item;就又不一樣了。這樣就變成了調用賦值操作符。

    合成復制構造函數

    復制構造函數是逐成員拷貝(memberwise copy)。

    即使我們不能對array進行copy,但是如果一個類包含有數組類型的成員,合成的復制構造函數也會拷貝這個的數組。數組中的每個元素都會進行復制。(Even though we ordinarily cannot copy an array, if a class has a member that is an array, then the synthesized copy constructor will copy the array. does so by copying each element.

    自定義拷貝函數

    class Foo {

         public:

            Foo();           // default constructor

            Foo(const Foo&); // copy constructor

            // ...

         };

    阻止拷貝

    方法:就是把拷貝函數聲明為private

    大多數類都應該定義拷貝構造函數和默認構造函數。

    如果一個類里面定義了一個構造函數,編譯期就不會再為這個類生成默認構造函數,而需要自己來定義了。

    溫習一下什么是默認構造函數:(唉,忘記的真快啊)

    默認構造函數沒有形參。如果定義的對象不提供初始化式(initializer)就會調用默認構造函數。(The default constructor is used whenever we define an object but do not supply an initializer.

    如果一個構造函數為所有形參提供缺省的實參,也可以叫做是默認構造函數。(A constructor that supplies default arguments for all its parameters also defines the default constructor.

    13.2 The Assignment Operator

    如果類自己沒有定義賦值操作符,那么編譯器合成賦值操作符。(注意,這活是編譯器干的)

    重載操作符(overloaded operators

    操作符重載的形參列表(這里要包括this形參,如果操作符是成員函數的話)以及返回值必須和操作符所需要的操作數相同。

    這句話咋理解呢?

    Sales_item trans, accum;

    trans = accum;

    1.            形參列表

    操作符’=’是二元操作符,它的操作數是兩個:第一個操作數是左邊的操作數,第二個操作數是右邊的操作數。上面這個例子,如果我們需要重載’=’,第一個操作數是被綁定到this指針上,第二個操作數是一個Sales_item類型的對象一般來說,右邊操作數一般都是作為const引用傳遞。Usually, the right-hand operand is passed as a const reference.)。

    Sales_item& operator=(const Sales_item &);

    2.            返回值

    賦值操作符的返回值類型應該和內置類型的返回值類型相同。(The return type from the assignment operator should be the same as the return from assignment for the built-in types)內置類型的賦值返回的是左操作數的引用,因此賦值操作符也必須返回和它的類類型相同的引用。具體到Sales_item’=’操作符重載的返回值是Sales_item的引用。

    class Sales_item {

     public:

          // other members as before

          // equivalent to the synthesized assignment operator

          Sales_item& operator=(const Sales_item &);

     };

    合成賦值操作符

    合成賦值操作符也是逐個成員賦值(memberwise assignment)。對于數組是對每個元素進行賦值。

    // equivalent to the synthesized assignment operator

     Sales_item& Sales_item::operator=(const Sales_item &rhs)

     {

          isbn = rhs.isbn;              // calls string::operator=

          units_sold = rhs.units_sold; // uses built-in int assignment

          revenue = rhs.revenue;        // uses built-in double assignment

          return *this;

     }

    13.3 The Destructor

    什么時候調用析構函數?

    // p points to default constructed object

       Sales_item *p = new Sales_item;

       {

           // new scope

           Sales_item item(*p); // copy constructor copies *p into item

           delete p;             // destructor called on object pointed to by p

       }         

    以上這個例子說明在兩種情況下會調用析構函數:

    1. 當變量在作用域范圍之外的時候,自動被撤銷(destroied
    2. 指向對象的指針被刪除(deleted),這個對象也就被撤銷(destroied

    進一步說明的是指向對象的指針或者是引用即使出了作用域,析構函數也是不會被執行的。就還是以上面的例子來說明:

    // p points to default constructed object

       Sales_item *p = new Sales_item;

       {

           // new scope

           Sales_item *ghost = new Sales_item;

           Sales_item item(*p); // copy constructor copies *p into item

           delete p;             // destructor called on object pointed to by p

       }         

    ghost這個小鬼即使出了作用域實際上也是沒有被刪除滴,占用的內存空間也是沒有被釋放滴。這樣的程序跑上N遍,機器就會想老牛一樣慢了。哎:(

    另外當容器撤銷時,容器中的元素的析構函數也會被調用(Destructors are also run on the elements of class type in a container - whether a library container or built-in array - when the container is destroyed

    啥時需要寫顯式的析構函數

    析構函數用來釋放構造函數或對象生存周期內所需的資源( Ordinarily they are used to relinquish resources acquired in the constructor or during the lifetime of the object.)

    另外析構函數也不僅僅是用來釋放資源。析構函數可以執行類設計者希望執行的任何操作,這些操作和類對象使用完畢之后執行。(A destructor is not limited only to relinquishing resources. A destructor, in general, can perform any operation that the class designer wishes to have executed subsequent to the last use of an object of that class.

    首要原則是:如果類需要析構函數,那么它一定也需要拷貝構造函數(copy constructor)和賦值操作符(assignment operator)。

    合成析構函數

    析構函數和拷貝構造函數(copy constructor)和賦值操作符(assignment operator)不同,就是即使你定義了自己的析構函數,當delete時,先調用你自己的析構函數,然后還是要調用合成的析構函數(synthesized destructor)。

    析構函數執行的順序:和構造函數恰恰相反。按照成員在類里面定義的相反的順序撤銷成員。(it destroys the members in reverse order from which they are declared in the class. For each member that is of class type, the synthesized destructor invokes that member's destructor to destroy the object.

    自定義析構函數和合成析構函數的執行順序:先自定義析構函數,然后再執行合成析構函數。

    class Sales_item {

     public:

         // empty; no work to do other than destroying the members,

         // which happens automatically

          ~Sales_item() { }

         // other members as before

     };

    13.4 A Message-Handling Example

    需求描述:

    1. 新建Message:是和folder無關的,通過調用saveMessage保存到指定的folder。一個Message可以同時屬于不同的folder。因此Message中就包含了一個folder的指針集合。另外每個folder里也要包括指向這條Message的指針。
    2. copy Message:包括拷貝Message的文本內容以及一系列的folder指針。同時對于每個folder也要追加一個指向拷貝后的Message的指針。
    3. 賦值操作(assignment):這個最搞:D。先要把等號左邊的message對象從folder中刪除,再刪除對象;然后把右邊message對象的文本內容和folder拷貝過來,同時還要向folder指針追加指向左邊message的指針。
    4. destroy:除了要撤銷這個Message對象,同時也要刪除掉各個folder里面指向這個Message的指針。

    大師抽象出來兩個操作:

    1. messagefolder中刪除:

    void remove_Msg_from_Folders();

    1. message追加到指定的folider

    void put_Msg_in_Folders(const std::set<Folder*>&);

    拷貝構造函數

    如果我們定義自己的拷貝構造函數,那么我們必須顯式拷貝任何我們想要拷貝的成員,因為顯式定義考別構造函數是不會自動拷貝任何東西的。(When we write our own copy constructor, we must explicitly copy any members that we want copied. An explicitly defined copy constructor copies nothing automatically.)就是說你要打算自己干就全部自己干,別指望編譯器會為你拾遺補缺。

    13.5 Managing Pointer Members

    Smart Point

    大師給出的辦法就是對指針進行封裝,定義一個新類,它包含有指針,以及使用的次數。下面這個類的定義高!實在是高!就是這個友元的定義。

    // private class for use by HasPtr only

     class U_Ptr {

          friend class HasPtr;

          int *ip;

          size_t use;

          U_Ptr(int *p): ip(p), use(1) { }

          ~U_Ptr() { delete ip; }

     };

    拷貝控制成員copy-control members

    包含指針成員的對象經常需要定義拷貝-控制成員。(Objects with pointer members often need to define the copy-control members.

    拷貝-控制成員包括:

    賦值操作(assignment operator

    析構函數

    拷貝構造函數(copy constructor

    smart pointer類,使用計數器來管理它smart pointer類。拷貝-控制成員都會影響計數器的值。

    復習澄清一下:

    ‘.’點操作符,’*’解引用操作符的優先級

    ‘.’點操作符的優先級高于解引用,所以要這樣子寫:

    Sales_item *sp = &item1;

    (*sp).same_isbn(item2); // run same_isbn on object to which sp points

    valuelike classespointlike classes有什么區別?

    這僅僅是一種很說法而已,valuelike classes,它的值copy后實際上是對應兩個對象;而pointlike classescopy的是指針,因此copy后實際上是指向的同一個對象。

    posted on 2009-06-24 08:17 amenglai 閱讀(530) 評論(0)  編輯  收藏 所屬分類: C++ Primer 之 讀書筆記

    主站蜘蛛池模板: 国产福利电影一区二区三区,亚洲国模精品一区 | 99久久成人国产精品免费 | 热99re久久免费视精品频软件 | 久久亚洲国产成人亚| 91免费国产视频| 久久精品亚洲一区二区| baoyu777永久免费视频| 亚洲一区中文字幕久久| 中文免费观看视频网站| 亚洲精品二三区伊人久久| 成年女人18级毛片毛片免费| 亚洲另类无码一区二区三区| 国产jizzjizz免费看jizz| 国产成人亚洲午夜电影| 国产成人麻豆亚洲综合无码精品| 手机看片国产免费永久| 老色鬼久久亚洲AV综合| 动漫黄网站免费永久在线观看 | 在线看片免费人成视频播| 亚洲大片在线观看| 久久久久久99av无码免费网站 | 999任你躁在线精品免费不卡| 亚洲精品一卡2卡3卡三卡四卡| 男人的好看免费观看在线视频| 亚洲Aⅴ在线无码播放毛片一线天| 亚洲国产精品成人久久蜜臀| 99免费在线视频| 亚洲日本在线播放| 国产一级做a爱免费视频| 中文字幕手机在线免费看电影| 亚洲国产精品国自产拍电影| 成人免费a级毛片| 中文字幕乱码系列免费| 亚洲男女一区二区三区| 免费国产成人高清视频网站| 你懂的网址免费国产| 亚洲人成综合网站7777香蕉| 亚洲一级片内射网站在线观看| 国产精品免费福利久久| 亚洲日本VA午夜在线电影| 亚洲免费观看视频|