青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

巢穴

about:blank

<轉>c++智能指針的創(chuàng)建(個人覺得講的超贊&清晰)

zero 坐在餐桌前,機械的重復“夾菜 -> 咀嚼 -> 吞咽”的動作序列,臉上用無形的大字寫著:我心不在焉。在他的對面坐著 Solmyr ,慢條斯理的吃著他那份午餐,維持著他一貫很有修養(yǎng)的形象 ——— 或者按照 zero 這些熟悉他本質的人的說法:假象。

“怎么了 zero ?胃口不好么?”,基本填飽肚子之后,Solmyr 覺得似乎應該關心一下他的學徒了。

“呃,沒什么,只是 …… Solmyr ,C++ 為什么不支持垃圾收集呢?(注:垃圾收集是一種機制,保證動態(tài)分配了的內存塊會自動釋放,Java 等語言支持這一機制。)”

Solmyr 嘆了口氣,用一種平靜的眼神盯著 zero :“是不是在 BBS 上和人吵 C++ 和 Java 哪個更好?而且吵輸了?我早告訴過你,這種爭論再無聊不過了。”

“呃 …… 是”,zero 不得不承認 ——— Solmyr 的眼神雖然一點也不銳利,但是卻莫名其妙的讓 zero 產生了微微的恐懼感。

“而且,誰告訴你 C++ 不支持垃圾收集的?”

“啊!Solmyr 你不是開玩笑吧?!”

“zero 你得轉變一下觀念。我問你,C++ 支不支持可以動態(tài)改變大小的數組?”

“這 …… 好象也沒有吧?”

“那 vector 是什么東西?”

“呃 ……”

“支持一種特性,并不是說非得把這個特性加到語法里去,我們也可以選擇用現有的語言機制實現一個庫來支持這個特征。以垃圾收集為例,這里我們的任務是要保證每一個被動態(tài)分配的內存塊都能夠被釋放,也就是說 ……”,Solmyr 不知從哪里找出了一張紙、一支筆,寫到:

 

int* p = new int; // 1
delete p; // 2

 

“也就是說,對于每一個 1 ,我們要保證有一個 2 被調用,1 和 2 必須成對出現。我來問你,C++ 中有什么東西是由語言本身保證一定成對出現的?”

“……”,zero 露出了努力搜索記憶的表情,不過很明顯一無所獲。

“提示一下,和類的創(chuàng)建有關。”

“哦!構造函數與析構函數!”

“正確。可惜普通指針沒有構造函數與析構函數,所以我們必須要寫一個類來加一層包裝,最簡單的就象這樣:”

 

class my_intptr
{
    public:
    int* m_p;

    my_intptr(int* p){ m_p = p; }
    ~my_intptr(){ delete m_p; }
};

…………

my_intptr pi(new int);
*(pi.m_p) = 10;

…………

 

“這里我們可以放心的使用 my_intptr ,不用擔心內存泄漏的問題:一旦 pi 這個變量被銷毀,我們知道 pi.p 指向的內存塊一定會被釋放。不過如果每次使用 my_intptr 都得去訪問它的成員未免太麻煩了。為此,可以給這個類加上重載的 * 運算符:”

 

class my_intptr
{
    private:
        int* m_p;

    public:
        my_intptr(int* p){ m_p = p; }
        ~my_intptr(){ delete m_p; }

        int& operator*(){ return *m_p; }
};

…………

my_intptr pi;
*pi = 10;
int a = *pi;

…………

 

“現在是不是看起來 my_intptr 就像是一個真正的指針了?正因為如此,這種技術被稱為智能指針。現在我問你,這個類還缺少哪些東西?”

zero 皺著眉頭,眼睛一眨一眨,看上去就像一臺慢速電腦正在辛苦的往它的硬盤上拷貝文件。良久,zero 抬起頭來,不太確定的說:“是不是還缺少一個拷貝構造函數和一個賦值運算符?”

“說說為什么。”,Solmyr 顯然不打算就這樣放過 zero。

“因為 …… 我記得沒錯的話 …… 《50 誡 》(注:指《Effective C++ 2/e》一書)中提到過,如果你的類里面有指針指向動態(tài)分配的內存,那么一定要為它寫一個拷貝構造函數和一個賦值運算符 …… 因為 …… 否則的話,一旦你做了賦值,會導致兩個對象的指針指向同一塊內存。對了!如果是上面的類,這樣一來會導致同一個指針被 delete 兩次!”

“正確。那么我們應該怎樣來實現呢?”

“這簡單,我們用 memcpy 把目標指針指向的內存中的內容拷貝過來。”

“如果我們的智能指針指向一個類的對象怎么辦?注意,類的對象中可能有指針,不能用 memcpy。”

“那 …… 我們用拷貝構造的辦法。”

“如果我們的智能指針指向的對象不能拷貝構造怎么辦?它可能有一個私有的拷貝構造函數。”

“那 ……”,zero 頓了一頓,決定老實承認,“我不知道。”

“問題在哪你知道么?在于你沒有把智能指針看作指針。想象一下,如果我們對一個指針做賦值,它的含義是什么?”

“呃,我明白了,在這種情況下,應該想辦法讓兩個智能指針指向同一個對象 …… 可是 Solmyr ,這樣以來豈不是仍然要對同一個對象刪除兩遍?”

“是的,我們得想辦法解決這個問題,辦法不只一種。比較好的一種是為每個指針維護一個引用計數值,每次賦值或者拷貝構造,就讓計數值加一,這意味著指向這個內存塊的智能指針又多了一個;而每有一個智能指針被銷毀,就讓計數值減一,這意味著指向這個內存塊的智能指針少了一個;一旦計數值為 0 ,就釋放內存塊。象這樣:”

 

class my_intptr
{
    private:
        int* m_p;
        int* m_count;

    public:
        my_intptr(int* p)
        {
             m_p = p;
             m_count = new int;

            // 初始化計數值為 1
            *m_count = 1;
        }
        my_intptr(const my_intptr& rhs) // 拷貝構造函數
       {
            m_p = rhs.m_p; // 指向同一塊內存
            m_count = rhs.m_count; // 使用同一個計數值
           (*m_count)++; // 計數值加 1
       }
       ~my_intptr()
      {
           (*m_count)--; // 計數值減 1
          if( *m_count == 0 ) // 已經沒有別的指針指向該內存塊了
         {
              delete m_p;
              delete m_count;
         }
      }

      my_intptr& operator=(const my_intptr& rhs)
     {
          if( m_p == rhs.m_p ) // 首先判斷是否本來就指向同一內存塊
                return *this; // 是則直接返回

          (*m_count)--; // 計數值減 1 ,因為該指針不再指向原來內存塊了
         if( *m_count == 0 ) // 已經沒有別的指針指向原來內存塊了
         {
              delete m_p;
              delete m_count;
          }

          m_p = rhs.m_p; // 指向同一塊內存
          m_count = rhs.m_count; // 使用同一個計數值
         (*m_count)++; // 計數值加 1
    }

…………
};

 

“其他部分沒有什么太大變化,我不費事了。現在想象一下我們怎樣使用這種智能指針?”,Solmyr 放下了筆,再次拿起了筷子,有些惋惜的發(fā)現他愛吃的肉丸子已經冷了。

zero 想象著,有些遲疑。“我們 …… 可以用 new int 表達式作為構造函數的參數來構造一個智能指針,然后 …… 然后我們可以任意的賦值,”,他開始抓住了思路,越說越快,“任意的用已經存在的智能指針來構造新的智能指針,智能指針的賦值運算符、拷貝構造函數和析構會保證計數值始終等于指向該內存塊的智能指針數。”zero 似乎明白了他看到了怎樣的功能,開始激動起來:“然后一旦計數值為 0 被分配的內存塊就會釋放!也就是說 …… 有指針指向內存塊,它就不釋放,一旦沒有,它就自動釋放!太棒了!我們只要一開始正確的初始化智能指針,就可以象普通指針那樣使用它,而且完全不用擔心內存釋放的問題!太棒了!”zero 激動的大叫:“這就是垃圾收集!Solmyr !我們在飯桌上實現了一個垃圾收集器!”

Solmyr 很明顯沒有分享 zero 的激動:“我在吃飯,你能不能不要大叫‘飯桌上實現了一個垃圾收集器’這種倒胃口的話?”頓了一頓,Solmyr 帶著他招牌式的壞笑,以一種可惡的口吻說道:“而且請注意一下自己的形象。”

“嗯?”,zero 回過神來,發(fā)現自己不知什么時候站了起來,而整個餐廳里的人都在看著他嘿嘿偷笑,這讓他感覺自己像個傻瓜。

zero 紅著臉坐下,壓低了聲音問 Solmyr :“不過 Solmyr ,這確實是一個的垃圾收集機制啊,只要我們把這個類改成 …… 嗯 …… 改成模板類,象這樣:”zero 抓過了紙筆,寫到:

 

template <typename T>
class my_ptr
{
    private:
    T* m_p;
    int* m_count;
    …………
};

 

“它不就能支持任意類型的指針了嗎?我們就可以把它用在任何地方。”

Solmyr 搖了搖頭:“不,你把問題想的太簡單了。對于簡單的類型,這個類確實可以處理的很好,但實際情況是很復雜的。考慮一個典型情況:類 Derived 是類 Base 的派生類,我們希望這樣賦值:”

Base* pb;
Derived pd;
…………
pb = pd;

“你倒說說看,這種情況,怎樣改用上面這個智能指針來處理?”

“……”,zero 沉默了。

“要實現一個完整的垃圾收集機制并不容易,因為有許多細節(jié)要考慮。”,Solmyr 開始總結了,“不過,基本思路就是上面說的這些。值得慶幸的是,目前已經有了一個相當成熟的‘引用計數’智能指針,boost::shared_ptr。大多數情況下,我們都可以使用它。另外,除了智能指針之外,還有一些技術也能夠幫助我們避開釋放內存的問題,比如內存池。但是,關鍵在于 ——— ”

Solmyr 再度用那種平靜的眼神盯著 zero :

“身為 C/C++ 程序員,必須有創(chuàng)造力。那種躺在語言機制上不思進取的人,那種必須要靠語法強制才知道怎樣編程的人,那種沒有別人告訴他該干什么就無所適從的人,不適合這門語言。”

 

 

歡迎訪問夢斷酒醒的博客:http://www.yanzhijun.com

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/ishallwin/archive/2009/09/08/4533145.aspx

posted on 2010-03-18 13:08 Vincent 閱讀(405) 評論(0)  編輯 收藏 引用 所屬分類: c++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品视频大全| 欧美性视频网站| 国模私拍一区二区三区| 欧美在线播放高清精品| 亚洲欧美日韩综合| 国产日韩一级二级三级| 久久精品一二三| 久久久久91| 亚洲免费观看在线观看| 亚洲精品少妇网址| 国产精品国产三级欧美二区| 羞羞视频在线观看欧美| 久久国产精品久久久久久电车| 韩国av一区二区三区在线观看| 久热精品视频在线| 欧美成人免费观看| 99在线精品免费视频九九视| 亚洲视频一区在线| 激情91久久| 亚洲老板91色精品久久| 国产欧美日韩精品一区| 麻豆免费精品视频| 欧美午夜三级| 欧美国产欧美综合 | 最新国产拍偷乱拍精品| 欧美国产大片| 久久精品亚洲乱码伦伦中文| 久久一二三四| 亚洲欧美中文日韩v在线观看| 久久精品免费| 亚洲一区二区三区视频播放| 欧美一区二区三区婷婷月色| 亚洲免费黄色| 久久视频精品在线| 亚洲欧美自拍偷拍| 欧美精品成人在线| 久久精品一区二区| 欧美午夜精品久久久久久人妖| 美女网站久久| 国产精品视频内| 亚洲精品久久久蜜桃| 韩国v欧美v日本v亚洲v| 一区二区三区高清| 亚洲精品乱码久久久久久日本蜜臀 | 久久精品综合网| 欧美日韩国产美| 免费国产自线拍一欧美视频| 国产精品亚洲人在线观看| 亚洲狼人精品一区二区三区| 伊伊综合在线| 久久精品视频播放| 欧美在线资源| 国产精品主播| 亚洲天堂黄色| 亚洲欧美综合网| 欧美性猛片xxxx免费看久爱| 亚洲人久久久| 日韩视频免费| 欧美日本国产视频| 91久久精品一区二区三区| 伊人婷婷久久| 麻豆av一区二区三区| 免费在线欧美视频| 在线观看欧美日韩| 久久综合国产精品台湾中文娱乐网| 久久九九免费视频| 国产婷婷精品| 久久久久国产一区二区| 久久免费精品视频| 在线播放日韩欧美| 噜噜噜久久亚洲精品国产品小说| 鲁大师成人一区二区三区| 黄色成人av在线| 美女脱光内衣内裤视频久久网站| 欧美黄色日本| 一区二区三区四区五区在线| 欧美午夜在线观看| 亚洲欧美国产另类| 老牛影视一区二区三区| 亚洲电影第1页| 欧美 日韩 国产一区二区在线视频| 欧美激情综合色| 一道本一区二区| 国产精品日韩专区| 久久久久久亚洲精品杨幂换脸 | 日韩视频中文字幕| 亚洲欧美日韩区| 一区二区三区在线高清| 欧美精品一区二区三| 亚洲视频一区二区在线观看| 久久久999精品免费| 黄色成人av| 欧美日韩成人精品| 欧美亚洲综合另类| 亚洲国产天堂久久综合网| 亚洲图片欧洲图片av| 国产裸体写真av一区二区| 久久综合电影| 99国产麻豆精品| 久久久美女艺术照精彩视频福利播放| 亚洲大片av| 国产精品va在线播放我和闺蜜| 亚欧美中日韩视频| 亚洲区免费影片| 久久久久在线观看| 亚洲深夜福利| 在线欧美日韩精品| 国产精品美女xx| 欧美成人黄色小视频| 欧美亚洲视频一区二区| 亚洲精品免费电影| 久久综合给合久久狠狠色| 亚洲一区在线直播| 亚洲精品日韩在线| 国产一区白浆| 国产精品激情偷乱一区二区∴| 久久青草欧美一区二区三区| 一本色道久久99精品综合| 欧美国产精品劲爆| 久久久久国产一区二区三区| 亚洲色图制服丝袜| 亚洲精品少妇30p| 尤物九九久久国产精品的分类| 国产精品在线看| 国产精品久久久久久久午夜片 | 美女视频一区免费观看| 亚洲欧美国产77777| 日韩一级成人av| 亚洲级视频在线观看免费1级| 久久国产主播精品| 亚洲女优在线| 亚洲综合99| 亚洲欧美日韩在线高清直播| 99国内精品| 一本大道久久a久久综合婷婷| 91久久线看在观草草青青| 国内精品一区二区三区| 国产欧美午夜| 国产婷婷一区二区| 国产亚洲欧美aaaa| 国产无一区二区| 国产最新精品精品你懂的| 国产日韩在线视频| 国产亚洲精品一区二区| 国产日产亚洲精品系列| 国产丝袜美腿一区二区三区| 国产伦精品一区二区| 国产亚洲精品久| 在线欧美日韩精品| 亚洲激情成人| 一本高清dvd不卡在线观看| 一区电影在线观看| 亚洲欧美精品suv| 午夜精品一区二区三区在线视| 亚洲综合首页| 欧美制服第一页| 麻豆精品在线视频| 91久久久亚洲精品| 一区二区三区久久久| 亚洲欧美日韩在线观看a三区| 午夜久久电影网| 久久久久一区二区| 欧美大片免费观看| 欧美日韩免费一区| 国产欧美精品日韩| 一区二区三区在线高清| 亚洲国产日韩一区| 亚洲一区二区伦理| 久久久精品日韩欧美| 欧美波霸影院| 亚洲精品乱码| 午夜精品久久| 欧美成人a∨高清免费观看| 欧美日韩大片| 国自产拍偷拍福利精品免费一| 亚洲精品一区二区三区不| 亚洲欧美日韩成人高清在线一区| 久久国产精品网站| 亚洲电影av在线| 午夜精品在线看| 欧美国产日韩一区二区在线观看 | 欧美一区二区黄| 欧美精品v日韩精品v国产精品| 国产精品美女xx| 亚洲日本一区二区三区| 午夜精品美女自拍福到在线| 欧美岛国激情| 亚洲男女自偷自拍| 欧美精品免费看| 一区二区三区在线观看欧美| 中文精品视频| 欧美电影免费观看大全| 亚洲一区二区三区免费观看 | 欧美岛国在线观看| 国产日韩专区| 亚洲自拍电影| 亚洲精品三级| 欧美高清视频免费观看| 黑人巨大精品欧美一区二区小视频 | 欧美精品亚洲一区二区在线播放|