DirectX11--ComPtr智能指針

綜述

DirectX11 With Windows SDK完整目錄html

歡迎加入QQ羣: 727623616 能夠一塊兒探討DX11,以及有什麼問題也能夠在這裏彙報。框架

IUnknown接口類

DirectX11的API是由一系列的COM組件來管理的,這些前綴帶I的接口類最終都繼承自IUnknown接口類。IUnknown的三個方法以下:函數

方法 描述
IUnknown::AddRef 內部引用計數加1。在每次複製了一個這樣的指針後,應當調用該方法以保證計數準確性
IUnknown::QueryInterface 查詢該實例是否實現了另外一個接口,若是存在則返回該接口的指針,而且對該接口的引用計數加1
IUnknown::Release 內部引用數減1。只有當內部引用數到達0時纔會真正釋放

在實際的使用狀況來看,一般咱們幾乎不會使用第一個方法。而用的最多的就是第三個方法了,每次用完該實例後,咱們必需要使用相似下面的宏來釋放:3d

#define ReleaseCOM(x) { if(x){ x->Release(); x = nullptr; } }

並且若是出現了忘記釋放某個接口指針的狀況話,內存泄漏的提醒就有可可以你去調試一成天了。指針

ComPtr智能指針

爲了解決上述問題,從繁雜的人工釋放中解脫,在本教程中大量使用了ComPtr智能指針。並且在龍書12的教程源碼中也用到了該智能指針。該智能指針能夠幫助咱們來管理這些COM組件實現的接口實例,而無需過多擔憂內存的泄漏。該智能指針的大小和通常的指針大小是一致的,沒有額外的內存空間佔用。因此本教程能夠不須要用到接口類ID3D11Debug來協助檢查內存泄漏。調試

使用該智能指針須要包含頭文件wrl/client.h,而且智能指針類模板ComPtr位於名稱空間Microsoft::WRL內。code

首先有五個比較經常使用的方法須要瞭解一下:htm

方法 描述
ComPtr ::Get 該方法返回T*,而且不會觸發引用計數加1,經常使用在COM組件接口的函數輸入
ComPtr ::GetAddressOf 該方法返回T**,經常使用在COM組件接口的函數輸出
ComPtr ::Reset 該方法對裏面的實例調用Release方法,並將指針置爲nullptr
ComPtr ::ReleaseAndGetAddressOf 該方法至關於先調用Reset方法,再調用GetAddressOf方法獲取T**,經常使用在COM組件接口的函數輸出,適用於實例可能會被反覆構造的狀況下
ComPtr ::As 一個模板函數,能夠替代IUnknown::QueryInterface的調用,須要傳遞一個ComPtr實例的地址

而後是一些運算符重載的方法:blog

運算符 描述
& 至關於調用了ComPtr<T>::ReleaseAndGetAddressOf方法,不推薦使用
-> 和裸指針的行爲一致
= 不要將裸指針指向的實例賦給它,若傳遞的是ComPtr 的不一樣實例則發生交換
==和!= 能夠和nullptr,或者另外一個ComPtr 實例進行比較

注意:大體在比10.0.16299.0更早的Windows SDK版本中,ComPtr使用了一個RemoveIUnknownBase類模板將IUnknown的三個接口都設爲了private,以防止用戶直接操做這些方法,這也就使得ComPtr沒法直接使用COM組件的QueryInterface方法。所以,使用ComPtr<T>::As是一種合適的選擇。繼承

我的建議,在使用該智能指針後就應該要避免使用IUnknown提供的三個接口方法來進行操做。

雖然替換成ComPtr後代碼量變長了,可是帶來的收益確定比你本身花費大量時間在檢查釋放內存上強的多。

下面的D3DApp將全部COM組件指針都換成了ComPtr

class D3DApp
{
public:
    D3DApp(HINSTANCE hInstance);              // 在構造函數的初始化列表應當設置好初始參數
    virtual ~D3DApp();

    HINSTANCE AppInst()const;                 // 獲取應用實例的句柄
    HWND      MainWnd()const;                 // 獲取主窗口句柄
    float     AspectRatio()const;             // 獲取屏幕寬高比

    int Run();                                // 運行程序,進行遊戲主循環

                                              // 框架方法。客戶派生類須要重載這些方法以實現特定的應用需求
    virtual bool Init();                      // 該父類方法須要初始化窗口和Direct3D部分
    virtual void OnResize();                  // 該父類方法須要在窗口大小變更的時候調用
    virtual void UpdateScene(float dt) = 0;   // 子類須要實現該方法,完成每一幀的更新
    virtual void DrawScene() = 0;             // 子類須要實現該方法,完成每一幀的繪製
    virtual LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    // 窗口的消息回調函數
protected:
    bool InitMainWindow();      // 窗口初始化
    bool InitDirect3D();        // Direct3D初始化

    void CalculateFrameStats(); // 計算每秒幀數並在窗口顯示

protected:

    HINSTANCE m_hAppInst;        // 應用實例句柄
    HWND      m_hMainWnd;        // 主窗口句柄
    bool      m_AppPaused;       // 應用是否暫停
    bool      m_Minimized;       // 應用是否最小化
    bool      m_Maximized;       // 應用是否最大化
    bool      m_Resizing;        // 窗口大小是否變化
    bool      m_Enable4xMsaa;    // 是否開啓4倍多重採樣
    UINT      m_4xMsaaQuality;   // MSAA支持的質量等級


    GameTimer m_Timer;           // 計時器

    // 使用模板別名(C++11)簡化類型名
    template <class T>
    using ComPtr = Microsoft::WRL::ComPtr<T>;
    // Direct3D 11
    ComPtr<ID3D11Device> m_pd3dDevice;                    // D3D11設備
    ComPtr<ID3D11DeviceContext> m_pd3dImmediateContext;   // D3D11設備上下文
    ComPtr<IDXGISwapChain> m_pSwapChain;                  // D3D11交換鏈
    // Direct3D 11.1
    ComPtr<ID3D11Device1> m_pd3dDevice1;                  // D3D11.1設備
    ComPtr<ID3D11DeviceContext1> m_pd3dImmediateContext1; // D3D11.1設備上下文
    ComPtr<IDXGISwapChain1> m_pSwapChain1;                // D3D11.1交換鏈
    // 經常使用資源
    ComPtr<ID3D11Texture2D> m_pDepthStencilBuffer;        // 深度模板緩衝區
    ComPtr<ID3D11RenderTargetView> m_pRenderTargetView;   // 渲染目標視圖
    ComPtr<ID3D11DepthStencilView> m_pDepthStencilView;   // 深度模板視圖
    D3D11_VIEWPORT m_ScreenViewport;                      // 視口

    // 派生類應該在構造函數設置好這些自定義的初始參數
    std::wstring m_MainWndCaption;                       // 主窗口標題
    int m_ClientWidth;                                   // 視口寬度
    int m_ClientHeight;                                  // 視口高度
};

DirectX11 With Windows SDK完整目錄

歡迎加入QQ羣: 727623616 能夠一塊兒探討DX11,以及有什麼問題也能夠在這裏彙報。

相關文章
相關標籤/搜索