• <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>

            拂曉·明月·彎刀

            觀望,等待只能讓出現的機會白白溜走

              C++博客 :: 首頁 ::  :: 聯系 :: 聚合  :: 管理 ::
                在Windows編程中,GDI資源的泄露一直是需要引起C++程序員的高度關注,一不小心,就會在函數的中途正常退出或者中途拋出異常退出的地方遺忘掉釋放前面申請的資源。本人也曾多次碰到這種問題,查閱了網上的資料,總是不能得到滿意的解決。最近看了下boost中的庫,才略有收獲,也算是拋磚引玉吧。
                要想解決上面的問題,就必須實現資源的自動釋放,類的析構函數正好可以滿足此要求,就象標準庫中智能指針就是這么實現的,但問題在于我們的參數個數,參數類型的不確定性。雖然重載和模板可以解決此問題(這也是我在網上看到的解決方法),但模板類的參數不具備自動推導能力(經傳入成員函數參數值推導出模板參數類型),而且過多的模板偏特化也不是我所擅長的,最主要是代碼的移植性無法保證。
                本文主要利用的boost中的bind庫,覺得仿函數的功能跟自己當前的需求不遠了,因為它們的共同點有:
            1. 可以接收任意多個模板參數(沒有具體驗證,至少是9個吧),
            2. 可以利用函數對模板參數類型的推導能力,省去了參數類型的指定。
            唯一不同的是bind后的仿函數是立即執行,不能具有類的析構函數自動執行的優點。目前需要解決的問題是推遲執行期,也既把operator()函數移到析構函數中執行,這就需要保存boost::bind(....)返回的對象,通過類的構造函數去保存,然后在析構函數中執行operator()就可以了。
                思路是出來了,但問題是boost::bind(...)函數返回的類型不確定,對象通過類模板是可以保存,但類沒有自動推導能力,還是無法實現,這里我就利用了boost::any的原理,正好解決了此問題,而且它也可以用于函數的延遲執行。詳見以下使用方法:
            步驟1: 實現類似于boost:;any的類,主要完成資源的自動釋放。實現如下:
            //SrcRelease.h頭文件
             1#ifndef _SRCRELEASE_INC_
             2#define _SRCRELEASE_INC_
             3
             4class CSrcRelease
             5{
             6public
             7    template<typename T>
             8    CSrcRelease(const T & value)
             9        : m_pHelder(new Helder<T>(value))
            10    {
            11    }

            12
            13    ~CSrcRelease()
            14    {
            15        delete m_pHelder;
            16    }

            17
            18private
            19    class IHelder
            20    {
            21    public:
            22        virtual ~IHelder() {}
            23    }
            ;
            24
            25    template<typename T>
            26    class Helder : public IHelder
            27    {
            28    public
            29        Helder(const T & value)
            30            : held(value)
            31        {
            32        }

            33        ~Helder() 
            34        {
            35            held();
            36        }

            37
            38    public// representation
            39        T held;
            40    }
            ;
            41
            42    IHelder* m_pHelder;
            43}
            ;
            44
            45#endif //_SRCRELEASE_INC_ 
            46

            步驟2: 下載boost庫,因為只用到了boost::bind庫,所以無需編譯. 將頭文件目錄加入vs2005中。
            步驟3: 客戶端調用
            //main.cpp
             1#include "SrcRelease.h"
             2#include <iostream>
             3#include <Windows.h>
             4#include <boost/bind.hpp>
             5#include <cassert>
             6
             7void _stdcall InvokeStr(const char* szValue)
             8{
             9    std::cout<<szValue<<std::endl;
            10}

            11
            12bool _stdcall InvokeStr(const char* szValue, int a, int b)
            13{
            14    std::cout<<szValue<<"\ta: "<<a<<"\tb: "<<b<<std::endl;
            15    return true;
            16}

            17
            18int main()
            19{
            20    //由于API都是_stdcall調用,而vs2005環境都是默認_cdecl,所以需要修改vs2005環境
            21    HBITMAP hBitmap=reinterpret_cast<HBITMAP>(LoadImage(NULL, L"test.bmp", IMAGE_BITMAP, 00, LR_LOADFROMFILE));
            22    assert(hBitmap!=NULL);
            23    CSrcRelease aBitmapRelease(boost::bind(&DeleteObject, hBitmap));
            24
            25    std::cout<<"Invoke Outer Before"<<std::endl;
            26    CSrcRelease aRelease(boost::bind(&InvokeStr, "Invoke Outer After"85));
            27
            28    {
            29        std::cout<<"Invoke Inner Before"<<std::endl;
            30        CSrcRelease aRelease(boost::bind(&InvokeStr, "Invoke Inner After"));
            31        std::cout<<"Invoke Inner Middle"<<std::endl;
            32    }

            33
            34    std::cout<<"Invoke Outer Middle"<<std::endl;
            35    return 0;
            36}
             

            以上代碼在winxp+vs2005下測試通過,如有疑問,歡迎聯系: ietj@mail.21cn.com
             
                                                                        嘵月刀
                                                                        2008.3.5
            posted on 2009-10-23 14:50 一路風塵 閱讀(1391) 評論(1)  編輯 收藏 引用 所屬分類: C++技術/工作總結

            評論

            # re: C++ 資源釋放 2009-11-13 01:23 OwnWaterloo
            any會使用動態內存,效率比較低。而且,你也不希望看到如下代碼:
            CSrcRelease ... 產生異常吧?

            可以用function<void ()>來保存bind的結果,并在析構函數中調用。
            或者,使用Loki::ScopeGuard。

              回復  更多評論
              

            狠狠88综合久久久久综合网| 香港aa三级久久三级老师2021国产三级精品三级在 | 2020最新久久久视精品爱| 99久久免费只有精品国产| 伊人情人综合成人久久网小说| 久久亚洲精品无码aⅴ大香| 久久久免费精品re6| 久久人妻少妇嫩草AV无码蜜桃| 久久亚洲AV无码精品色午夜麻豆| 精品久久久久久国产潘金莲| 国产91久久综合| 久久久久亚洲av无码专区 | 99久久综合国产精品二区| 欧美亚洲国产精品久久| 99久久精品费精品国产| 久久精品亚洲AV久久久无码| 91精品国产91久久久久久蜜臀| 久久久久国产精品人妻| 精品无码久久久久久久久久| 91精品国产91久久综合| 久久久无码精品亚洲日韩京东传媒| 国内精品久久久久久久涩爱| 狠狠色丁香婷婷久久综合不卡| 久久精品无码一区二区WWW| 久久人人爽人爽人人爽av| 亚洲午夜久久久精品影院| 97久久超碰国产精品2021| 蜜臀av性久久久久蜜臀aⅴ麻豆| 久久综合色老色| 亚洲精品乱码久久久久久不卡| 久久国产精品免费一区| 国产精品欧美久久久久无广告 | 久久99热只有频精品8| 久久久久久久亚洲Av无码| 7777久久久国产精品消防器材| 精品久久久久久无码不卡| 少妇熟女久久综合网色欲| 婷婷国产天堂久久综合五月| 亚洲欧美久久久久9999| 狠狠色丁香久久婷婷综合_中 | 久久er热视频在这里精品|