亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

剖析C++模板會不會使代碼膨脹

2020-02-24 14:35:32
字體:
來源:轉載
供稿:網友

有人說C++模板會使代碼膨脹,可又人說不會,他的依據是 如果模板會使代碼膨脹, 那么ATL和WTL里為什么還要大量使用模板? 同樣功能 ,ATL和WTL編譯出的可執行文件可比MFC編譯的要小的多。我當時一愣 ,事實確實如同事所說,難道模板會使代碼膨脹的觀點是錯誤的嗎?接下來一起剖析C++模板會不會使代碼膨脹。

MFC因為本身代碼量和復雜性在那里, 所以它生成比較大的exe無可厚非。我們這里重點關注為什么ATL/WTL使用模板,但是卻不會使生成的exe變大。

我們知道使用模板時, 同一模板生成不同的模板實類后會是多份代碼 ,比如 vector, vector, vector, 這里總共會生成3份不同的vector代碼,這就是我們平時所說的代碼膨脹。

那么為什么ATL/WTL就沒有代碼膨脹的問題呢?
我這里以 ATL里的窗口代碼為例來分析這個問題,因為我對WinDbg比較熟悉,下面我會以WinDbg為工具來分析我以前的寫得那個俄羅斯方塊程序。

首先我們看一下ATL的窗口代碼:


template
class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT
{
public:
??? DECLARE_WND_CLASS(NULL)

?

??? static LPCTSTR GetWndCaption()
??? {
??????? return NULL;
??? }

??? HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
??????????? DWORD dwStyle = 0, DWORD dwExStyle = 0,
??????????? _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
??? {
??????? if (T::GetWndClassInfo().m_lpszOrigName == NULL)
??????????? T::GetWndClassInfo().m_lpszOrigName = GetWndClassName();
??????? ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);

??????? dwStyle = T::GetWndStyle(dwStyle);
??????? dwExStyle = T::GetWndExStyle(dwExStyle);

??????? // set caption
??????? if (szWindowName == NULL)
??????????? szWindowName = T::GetWndCaption();

??????? return CWindowImplBaseT::Create(hWndParent, rect, szWindowName,
??????????? dwStyle, dwExStyle, MenuOrID, atom, lpCreateParam);
??? }
};


上面是一個模板類,它應該會生成多份模板實例代碼:我們可以用WinDbg的符號搜索命令來做驗證:
輸入 x HYTeris!ATL::CWindowImpl

?

?


0:000> x HYTeris!ATL::CWindowImpl004592f0 HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
004343a0 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
00437c90 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
00430440 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
0041c990 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
0044cf50 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
004539a0 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
00435800 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
00434640 HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::~CWindowImpl,ATL::CWinTraits > (void)
00437440 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
00436020 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
00453f70 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
00424e30 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
004338a0 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
0041c4f0 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
00441b50 HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::CWindowImpl,ATL::CWinTraits > (void)
004365f0 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
00455120 HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::CWindowImpl,ATL::CWinTraits > (void)
0040ea20 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
00453fa0 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
0041abc0 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
00459c20 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
0045f640 HYTeris!ATL::CWindowImpl,ATL::CWinTraitsOR > >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
004608a0 HYTeris!ATL::CWindowImpl >::GetWndClassInfo (void)
0045fed0 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
00433a70 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
00437c60 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
0044fb70 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
0041acf0 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
00459510 HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::GetWndCaption (void)
00437a90 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
00430490 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
00424de0 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
00433ac0 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
00433850 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
00433b60 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
00452050 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
0044f8e0 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
0044cec0 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
004340e0 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
00433ef0 HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::~CWindowImpl,ATL::CWinTraits > (void)
004348c0 HYTeris!ATL::CWindowImpl,ATL::CWinTraitsOR > >::~CWindowImpl,ATL::CWinTraitsOR > > (void)
004535b0 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
00454170 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
00459c70 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
00451ed0 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
00451f20 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
0045c4b0 HYTeris!ATL::CWindowImpl >::CWindowImpl > (void)
00436320 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
004536a0 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
004604a0 HYTeris!ATL::CWindowImpl,ATL::CWinTraitsOR > >::GetWndCaption (void)
0040eca0 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
0045ff90 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
00437cc0 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
004366e0 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
0045e620 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
004608d0 HYTeris!ATL::CWindowImpl >::GetWndCaption (void)
004520a0 HYTeris!ATL::CWindowImpl >::~CWindowImpl > (void)
0045d210 HYTeris!ATL::CWindowImpl,ATL::CWinTraitsOR > >::CWindowImpl,ATL::CWinTraitsOR > > (void)
004d84a8 HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004d84b8 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004d7970 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004d7960 HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004d914c HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d8dd0 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d8b04 HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004d8b14 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004d8ae8 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004e31b8 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004e2980 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004d88c4 HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d8330 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d88f0 HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::`RTTI Base Class Array' =
004d88e0 HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::`RTTI Class Hierarchy Descriptor' =
004d8a40 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004e30f0 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004d8a5c HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004d8a6c HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004e21d0 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004d8c70 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004e2e78 HYTeris!ATL::CWindowImpl,ATL::CWinTraits > `RTTI Type Descriptor' =
004e1f00 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004d9208 HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004d9218 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004e1ad8 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004d834c HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004d835c HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004d8c9c HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004d8c8c HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004d856c HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004d855c HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004e2bb8 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004d7fa0 HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004d7fb0 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004d91ec HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004e2048 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004d8174 HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004d8184 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004d8dfc HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004d8dec HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004e2728 HYTeris!ATL::CWindowImpl,ATL::CWinTraits > `RTTI Type Descriptor' =
004e28c8 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004d8fac HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::`RTTI Base Class Array' =
004d8f9c HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::`RTTI Class Hierarchy Descriptor' =
004d848c HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d8f80 HYTeris!ATL::CWindowImpl,ATL::CWinTraits >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d8158 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d8540 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d7944 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d7f84 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004e2aa0 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004d9168 HYTeris!ATL::CWindowImpl >::`RTTI Class Hierarchy Descriptor' =
004d9178 HYTeris!ATL::CWindowImpl >::`RTTI Base Class Array' =
004e1628 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004e2148 HYTeris!ATL::CWindowImpl > `RTTI Type Descriptor' =
004d95c4 HYTeris!ATL::CWindowImpl,ATL::CWinTraitsOR > >::`RTTI Base Class Array' =
004d95b4 HYTeris!ATL::CWindowImpl,ATL::CWinTraitsOR > >::`RTTI Class Hierarchy Descriptor' =
004e3400 HYTeris!ATL::CWindowImpl,ATL::CWinTraitsOR > > `RTTI Type Descriptor' =
004d9598 HYTeris!ATL::CWindowImpl,ATL::CWinTraitsOR > >::`RTTI Base Class Descriptor at (0,-1,0,64)' =


上面的符號可以驗證我們多份實例的猜想。
可以看到 CWindowImpl和我們的窗口繼承類(T),窗口基類(TBase), 窗口風格(TWinTraits) 相關,所以數量很多 。? 那么為什么這么多的符號,也就是這么多的函數代碼 ,exe大小沒有被撐大?
那時因為CWindowImpl類函數本身很小, 我們從函數的 代碼量上就可以看出來。

?

用同樣的方法 ,我們可以繼續分析 CWindowImplBaseT


template
class ATL_NO_VTABLE CWindowImplBaseT : public CWindowImplRoot
{
public:
??? WNDPROC m_pfnSuperWindowProc;

?

??? CWindowImplBaseT() : m_pfnSuperWindowProc(::DefWindowProc)
??? {}

??? static DWORD GetWndStyle(DWORD dwStyle)
??? {
??????? return TWinTraits::GetWndStyle(dwStyle);
??? }
??? static DWORD GetWndExStyle(DWORD dwExStyle)
??? {
??????? return TWinTraits::GetWndExStyle(dwExStyle);
??? }

??? virtual WNDPROC GetWindowProc()
??? {
??????? return WindowProc;
??? }
??? static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
??? static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
??? HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName,
??????????? DWORD dwStyle, DWORD dwExStyle, _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam = NULL);
??? BOOL DestroyWindow()
??? {
??????? ATLASSERT(::IsWindow(m_hWnd));
??????? return ::DestroyWindow(m_hWnd);
??? }
??? BOOL SubclassWindow(HWND hWnd);
??? HWND UnsubclassWindow(BOOL bForce = FALSE);

??? LRESULT DefWindowProc()
??? {
??????? const _ATL_MSG* pMsg = m_pCurrentMsg;
??????? LRESULT lRes = 0;
??????? if (pMsg != NULL)
??????????? lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
??????? return lRes;
??? }

??? LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
??? {
#ifdef STRICT
??????? return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
#else
??????? return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
#endif
??? }

??? virtual void OnFinalMessage(HWND /*hWnd*/)
??? {
??????? // override to do something, if needed
??? }
};

?

?


0:000> x HYTeris!ATL::CWindowImplBaseT0040f170 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, unsigned short, void *)
0040ec20 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::GetWndStyle (unsigned long)
00435970 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::OnFinalMessage (struct HWND__ *)
004604d0 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::GetWndStyle (unsigned long)
00434a10 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::~CWindowImplBaseT<:ceditt>,ATL::CWinTraits > (void)
0040ec60 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::GetWndExStyle (unsigned long)
00461740 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::WindowProc (struct HWND__ *, unsigned int, unsigned int, long)
0044c040 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::WindowProc (struct HWND__ *, unsigned int, unsigned int, long)
004346e0 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::~CWindowImplBaseT<:cbuttont>,ATL::CWinTraits > (void)
0041c440 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::CWindowImplBaseT<:cwindow> > (void)
00435940 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::GetWindowProc (void)
00459580 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::GetWndExStyle (unsigned long)
00461950 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, unsigned short, void *)
004395b0 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::StartWindowProc (struct HWND__ *, unsigned int, unsigned int, long)
00439ea0 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::DefWindowProcW (unsigned int, unsigned int, long)
00461620 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::StartWindowProc (struct HWND__ *, unsigned int, unsigned int, long)
004596e0 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, unsigned short, void *)
0041ced0 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::WindowProc (struct HWND__ *, unsigned int, unsigned int, long)
0044c370 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::UnsubclassWindow (int)
00460510 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::GetWndExStyle (unsigned long)
00457f70 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::WindowProc (struct HWND__ *, unsigned int, unsigned int, long)
0045f830 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::GetWindowProc (void)
00457820 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits > (void)
004374b0 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::GetWndExStyle (unsigned long)
00434ad0 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::~CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > > (void)
004595c0 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::StartWindowProc (struct HWND__ *, unsigned int, unsigned int, long)
004358f0 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::CWindowImplBaseT<:cwindow> > (void)
00445920 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::OnFinalMessage (struct HWND__ *)
00461ad0 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::DefWindowProcW (unsigned int, unsigned int, long)
0041c4c0 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::OnFinalMessage (struct HWND__ *)
00437470 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::GetWndStyle (unsigned long)
004398e0 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::Create (struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, unsigned short, void *)
0040ed50 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::StartWindowProc (struct HWND__ *, unsigned int, unsigned int, long)
004458a0 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::CWindowImplBaseT<:ceditt>,ATL::CWinTraits > (void)
0045f7e0 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > > (void)
0041ad30 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::~CWindowImplBaseT<:cwindow> > (void)
00430550 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::~CWindowImplBaseT<:cwindow> > (void)
0045f860 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::OnFinalMessage (struct HWND__ *)
004582a0 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::UnsubclassWindow (int)
0041c490 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::GetWindowProc (void)
0044cb50 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::DefWindowProcW (unsigned int, unsigned int, long)
0044c250 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::SubclassWindow (struct HWND__ *)
004458f0 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::GetWindowProc (void)
00459540 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::GetWndStyle (unsigned long)
00458180 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::SubclassWindow (struct HWND__ *)
00457870 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::GetWindowProc (void)
00457910 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::OnFinalMessage (struct HWND__ *)
0040e990 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::DestroyWindow (void)
004396d0 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::WindowProc (struct HWND__ *, unsigned int, unsigned int, long)
0041d1c0 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::DefWindowProcW (unsigned int, unsigned int, long)
004578a0 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::DefWindowProcW (unsigned int, unsigned int, long)
004d8fc8 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d8ff4 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::`RTTI Base Class Array' =
004d8fe4 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits >::`RTTI Class Hierarchy Descriptor' =
004d79b4 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::`RTTI Base Class Array' =
004d79a4 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::`RTTI Class Hierarchy Descriptor' =
004e2798 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits > `RTTI Type Descriptor' =
004d819c HYTeris!ATL::CWindowImplBaseT<:cwindow> >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d8938 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::`RTTI Base Class Array' =
004d8928 HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::`RTTI Class Hierarchy Descriptor' =
004d960c HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::`RTTI Base Class Array' =
004d95fc HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::`RTTI Class Hierarchy Descriptor' =
004e2ee8 HYTeris!ATL::CWindowImplBaseT<:cbuttont>,ATL::CWinTraits > `RTTI Type Descriptor' =
004d81c8 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::`RTTI Base Class Array' =
004d81b8 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::`RTTI Class Hierarchy Descriptor' =
004e34a0 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > > `RTTI Type Descriptor' =
004d95e0 HYTeris!ATL::CWindowImplBaseT<:clistviewctrlt>,ATL::CWinTraitsOR > >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004e1f68 HYTeris!ATL::CWindowImplBaseT<:cwindow> > `RTTI Type Descriptor' =
004e1688 HYTeris!ATL::CWindowImplBaseT<:cwindow> > `RTTI Type Descriptor' =
004d7988 HYTeris!ATL::CWindowImplBaseT<:cwindow> >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d890c HYTeris!ATL::CWindowImplBaseT<:ceditt>,ATL::CWinTraits >::`RTTI Base Class Descriptor at (0,-1,0,64)' =


可以看到 CWindowImplBaseT只與 窗口基類和窗口風格相關 ,數量 已經減小很多 ,CWindowImplBaseT模板類本身函數數量不多 ,函數代碼量大小也不大 。

?

然后再看CWindowImplRoot,


template
class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap
{
public:
??? CWndProcThunk m_thunk;
??? const _ATL_MSG* m_pCurrentMsg;
??? DWORD m_dwState;

?

??? enum { WINSTATE_DESTROYED = 0x00000001 };

// Constructor/destructor
??? CWindowImplRoot() : m_pCurrentMsg(NULL), m_dwState(0)
??? { }

??? virtual ~CWindowImplRoot()
??? {
#ifdef _DEBUG
??????? if(m_hWnd != NULL)??? // should be cleared in WindowProc
??????? {
??????????? ATLTRACE(atlTraceWindowing, 0, _T("ERROR - Object deleted before window was destroyed/n"));
??????????? ATLASSERT(FALSE);
??????? }
#endif //_DEBUG
??? }

// Current message
??? const _ATL_MSG* GetCurrentMessage() const
??? {
??????? return m_pCurrentMsg;
??? }

??? // "handled" management for cracked handlers
??? BOOL IsMsgHandled() const
??? {
??????? const _ATL_MSG* pMsg = GetCurrentMessage();
??????? ATLASSERT(pMsg != NULL);
??????? ATLASSERT(pMsg->cbSize >= sizeof(_ATL_MSG));
??????? return pMsg->bHandled;
??? }
??? void SetMsgHandled(BOOL bHandled)
??? {
??????? _ATL_MSG* pMsg = (_ATL_MSG*)GetCurrentMessage();??? // override const
??????? ATLASSERT(pMsg != NULL);
??????? ATLASSERT(pMsg->cbSize >= sizeof(_ATL_MSG));
??????? pMsg->bHandled = bHandled;
??? }

// Message forwarding and reflection support
??? LRESULT ForwardNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
??? LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
??? static BOOL DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult);
};

?

?


0:000> x HYTeris!ATL::CWindowImplRoot*
004364d0 HYTeris!ATL::CWindowImplRoot<:clistviewctrlt> >::~CWindowImplRoot<:clistviewctrlt> > (void)
004367d0 HYTeris!ATL::CWindowImplRoot<:ceditt> >::~CWindowImplRoot<:ceditt> > (void)
00457c30 HYTeris!ATL::CWindowImplRoot<:cbuttont> >::CWindowImplRoot<:cbuttont> > (void)
00460550 HYTeris!ATL::CWindowImplRoot<:clistviewctrlt> >::CWindowImplRoot<:clistviewctrlt> > (void)
004479d0 HYTeris!ATL::CWindowImplRoot<:ceditt> >::CWindowImplRoot<:ceditt> > (void)
0041c360 HYTeris!ATL::CWindowImplRoot<:cwindow>::~CWindowImplRoot<:cwindow> (void)
00435f40 HYTeris!ATL::CWindowImplRoot<:cbuttont> >::~CWindowImplRoot<:cbuttont> > (void)
004613f0 HYTeris!ATL::CWindowImplRoot<:cwindow>::ForwardNotifications (unsigned int, unsigned int, long, int *)
00438f50 HYTeris!ATL::CWindowImplRoot<:cwindow>::ReflectNotifications (unsigned int, unsigned int, long, int *)
0041c8e0 HYTeris!ATL::CWindowImplRoot<:cwindow>::CWindowImplRoot<:cwindow> (void)
004e2800 HYTeris!ATL::CWindowImplRoot<:ceditt> > `RTTI Type Descriptor' =
004d897c HYTeris!ATL::CWindowImplRoot<:ceditt> >::`RTTI Base Class Array' =
004d896c HYTeris!ATL::CWindowImplRoot<:ceditt> >::`RTTI Class Hierarchy Descriptor' =
004d9640 HYTeris!ATL::CWindowImplRoot<:clistviewctrlt> >::`RTTI Class Hierarchy Descriptor' =
004d9650 HYTeris!ATL::CWindowImplRoot<:clistviewctrlt> >::`RTTI Base Class Array' =
004d8950 HYTeris!ATL::CWindowImplRoot<:ceditt> >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d9028 HYTeris!ATL::CWindowImplRoot<:cbuttont> >::`RTTI Class Hierarchy Descriptor' =
004d9038 HYTeris!ATL::CWindowImplRoot<:cbuttont> >::`RTTI Base Class Array' =
004e16dc HYTeris!ATL::CWindowImplRoot<:cwindow> `RTTI Type Descriptor' =
004e3530 HYTeris!ATL::CWindowImplRoot<:clistviewctrlt> > `RTTI Type Descriptor' =
004d9624 HYTeris!ATL::CWindowImplRoot<:clistviewctrlt> >::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d79c8 HYTeris!ATL::CWindowImplRoot<:cwindow>::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004e2f58 HYTeris!ATL::CWindowImplRoot<:cbuttont> > `RTTI Type Descriptor' =
004d79f4 HYTeris!ATL::CWindowImplRoot<:cwindow>::`RTTI Base Class Array' =
004d79e4 HYTeris!ATL::CWindowImplRoot<:cwindow>::`RTTI Class Hierarchy Descriptor' =
004d900c HYTeris!ATL::CWindowImplRoot<:cbuttont> >::`RTTI Base Class Descriptor at (0,-1,0,64)' =


可以看到 CWindowImplRoot只和窗口基類(CWindow)相關 ,所以 相關的符號就更少了。

?

最后我們再看一下CWindow:


0:000> x HYTeris!ATL::CWindow::*
004e1000 HYTeris!ATL::CWindow::rcDefault = struct tagRECT
00442a20 HYTeris!ATL::CWindow::DestroyWindow (void)
00425730 HYTeris!ATL::CWindow::InvalidateRect (struct tagRECT *, int)
00442340 HYTeris!ATL::CWindow::CenterWindow (struct HWND__ *)
00425850 HYTeris!ATL::CWindow::UpdateWindow (void)
0041c950 HYTeris!ATL::CWindow::CWindow (struct HWND__ *)
004391e0 HYTeris!ATL::CWindow::GetDlgItem (int)
004568a0 HYTeris!ATL::CWindow::SetWindowRgn (struct HRGN__ *, int)
00441d20 HYTeris!ATL::CWindow::GetWindowLongW (int)
00444350 HYTeris!ATL::CWindow::Create (wchar_t *, struct HWND__ *, class ATL::_U_RECT, wchar_t *, unsigned long, unsigned long, class ATL::_U_MENUorID, void *)
004391b0 HYTeris!ATL::CWindow::operator HWND__ * (void)
00459080 HYTeris!ATL::CWindow::EnableWindow (int)
00425140 HYTeris!ATL::CWindow::GetClientRect (struct tagRECT *)
00430c70 HYTeris!ATL::CWindow::SetWindowTextW (wchar_t *)
0040eb30 HYTeris!ATL::CWindow::GetWndClassName (void)
00456770 HYTeris!ATL::CWindow::MoveWindow (int, int, int, int, int)
00442ac0 HYTeris!ATL::CWindow::KillTimer (unsigned int)
00455fc0 HYTeris!ATL::CWindow::GetWindowTextW (wchar_t *, int)
0040ba20 HYTeris!ATL::CWindow::IsWindow (void)
00441db0 HYTeris!ATL::CWindow::GetParent (void)
004315b0 HYTeris!ATL::CWindow::SetWindowPos (struct HWND__ *, int, int, int, int, unsigned int)
00456810 HYTeris!ATL::CWindow::GetWindowRect (struct tagRECT *)
00431860 HYTeris!ATL::CWindow::GetStyle (void)
00455250 HYTeris!ATL::CWindow::Invalidate (int)
004318f0 HYTeris!ATL::CWindow::SetCapture (void)
00442cf0 HYTeris!ATL::CWindow::SetTimer (unsigned int, unsigned int, *)
00431980 HYTeris!ATL::CWindow::ModifyStyle (unsigned long, unsigned long, unsigned int)
00443d10 HYTeris!ATL::CWindow::GetDlgItemTextW (int, wchar_t *, int)
0040b980 HYTeris!ATL::CWindow::SendMessageW (unsigned int, unsigned int, long)
00434be0 HYTeris!ATL::CWindow::ShowWindow (int)
004d7a38 HYTeris!ATL::CWindow::`RTTI Base Class Descriptor at (0,-1,0,64)' =
004d7a04 HYTeris!ATL::CWindow::`RTTI Base Class Descriptor at (4,-1,0,64)' =
004d7a20 HYTeris!ATL::CWindow::`RTTI Class Hierarchy Descriptor' =
004d7a30 HYTeris!ATL::CWindow::`RTTI Base Class Array' =


我們看到CWindow只有一份 , 并且函數數量相比AtlWin.h減少了很多,因為ATL是以源代碼的方式提供的 ,所有沒有用到的函數不會被編譯到我們最終的可執行文件中 。

?

通過上面的分析 ,相信我們知道了為什么ATL/WTL大量使用模板,但是生成的exe還是這么小的原因 :
不是模板不會使代碼膨脹,而是ATL/WTL在設計時就關注了這個問題 ,它避免了在可能生成很多模板實例的模板類中編寫大量代碼(有些拗口,不知道你有沒有讀懂^_^)

總結下 ,如果你想用模板,但是又不想 讓自己最終的可執行文件變的很大,
有2種方式:
(1)你的模板類不會生成很多模板實例,這樣寫成模板類還有意義嗎?
(2)你的模板類的代碼量或是函數個數很少,你可以仿照ATL的方式把模板無關的東西用繼承的方式逐層剝離,確保模板類的代碼都是和模板參數相關的。

到這里,剖析C++模板會不會使代碼膨脹的介紹就算完成了,如果大家還有不清楚地方可以留言給我,如果覺得我寫得不錯的話,請給我一個大拇指,謝謝!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲人成网在线播放| 亚洲网站视频福利| 亚洲欧美成人网| 91免费国产视频| 少妇久久久久久| 在线观看不卡av| 亚洲a在线观看| 亚洲精品一区中文字幕乱码| 国产视频精品xxxx| 在线精品国产成人综合| 国产精品美女久久| 成人网在线视频| 亚洲电影免费观看高清完整版在线观看| 精品无人区乱码1区2区3区在线| 黑人精品xxx一区一二区| 亚洲精品中文字幕av| 国产一区二区三区在线播放免费观看| 91精品国产自产在线观看永久| 久久成年人免费电影| 一区二区成人av| 韩国精品久久久999| 亚洲色图17p| 成人网在线免费观看| 亚洲一区二区三区四区在线播放| 亚洲视频欧洲视频| 欧美www视频在线观看| 亚洲最大成人在线| 亚洲成人网av| 欧美激情二区三区| 久久乐国产精品| 在线播放国产一区中文字幕剧情欧美| 国产精品青青在线观看爽香蕉| 91久久久精品| 69av视频在线播放| 日韩在线视频中文字幕| 2019中文字幕在线免费观看| 欧美大片网站在线观看| 国产日韩欧美中文在线播放| 久热精品视频在线免费观看| 亲爱的老师9免费观看全集电视剧| 视频一区视频二区国产精品| 亚洲高清福利视频| 亲爱的老师9免费观看全集电视剧| 亚洲激情视频在线| 欧美日韩国产二区| 国产成人精品久久亚洲高清不卡| 92看片淫黄大片看国产片| 国产视频久久久久| 国内精品久久久久久| 91精品久久久久久久久久入口| 91在线视频导航| 久久视频在线看| 久久久久久久电影一区| 欧洲成人午夜免费大片| 久久九九精品99国产精品| 欧美一级电影免费在线观看| 国产脚交av在线一区二区| 91色视频在线观看| 国产日韩在线看片| 久久精品人人爽| 国产精品免费久久久| 日本国产精品视频| 亚洲欧美综合图区| 国产美女精品视频免费观看| 久久精品国产99国产精品澳门| 欧美猛男性生活免费| 8x拔播拔播x8国产精品| 国产成人短视频| 国产精品爽爽爽| 亚洲色图国产精品| 亚洲欧美中文字幕在线一区| 欧美激情精品久久久| 亚洲一区二区精品| 疯狂做受xxxx高潮欧美日本| 亚洲综合色激情五月| 亚洲欧洲自拍偷拍| 亚洲视频一区二区| 国产日韩在线一区| 精品亚洲一区二区三区| 国产精品久久久久久久久久三级| 欧美成人精品影院| 黑人精品xxx一区| 亚洲综合精品伊人久久| 久久精品国产欧美亚洲人人爽| 欧美亚洲视频在线看网址| 久久琪琪电影院| 亚洲成人免费在线视频| 亚洲亚裔videos黑人hd| 亚洲第一网站免费视频| 国产午夜一区二区| 国产精品网站视频| 青青草国产精品一区二区| 国产a∨精品一区二区三区不卡| 国产在线拍揄自揄视频不卡99| 日韩经典第一页| 欧美激情亚洲自拍| 国产欧美日韩高清| 国产中文字幕亚洲| 久久国产视频网站| 欧美日韩国产二区| 欧美在线视频网| 国产精品69久久| 97视频免费观看| 狠狠躁夜夜躁人人躁婷婷91| 日韩精品视频免费在线观看| 国内精品久久影院| 欧美日韩精品中文字幕| 国产91在线播放九色快色| 久久久久中文字幕2018| 68精品国产免费久久久久久婷婷| 日韩大陆毛片av| 日韩欧美亚洲成人| 亚洲一区亚洲二区亚洲三区| 91免费看国产| …久久精品99久久香蕉国产| 国产91精品黑色丝袜高跟鞋| 欧美精品在线播放| 欧美成人h版在线观看| 色诱女教师一区二区三区| 日本高清久久天堂| 亚洲国产91色在线| 亚洲精品自拍视频| 亚洲欧美制服丝袜| 日本sm极度另类视频| 国产精品久久视频| 欧美体内谢she精2性欧美| 国产精品自拍小视频| 高清日韩电视剧大全免费播放在线观看| 国产欧美在线观看| 欧美一级片久久久久久久| 日韩中文字幕第一页| 黑人巨大精品欧美一区免费视频| 国产亚洲精品久久久久久777| 日韩欧美在线免费| 性日韩欧美在线视频| 国产精品热视频| 国产91精品久久久久久久| 亚洲精品999| 97成人在线视频| 欧美日韩国产一区中文午夜| 国产精品一区二区久久精品| 欧美成人自拍视频| 久久91精品国产91久久跳| 91手机视频在线观看| 日韩亚洲在线观看| 亚洲国产成人精品一区二区| 欧美性极品少妇精品网站| 一本色道久久综合狠狠躁篇怎么玩| 久久香蕉频线观| 97成人在线视频| 久久香蕉频线观| 日韩亚洲欧美中文高清在线| 国产高清视频一区三区| 51午夜精品视频| 欧美亚洲另类激情另类| 久久精品2019中文字幕| 久久69精品久久久久久国产越南| 亚洲国产欧美自拍| 视频直播国产精品| 91精品视频网站| 国产成人精品免高潮在线观看| 亚洲最大av网| 久久久人成影片一区二区三区| 久久久电影免费观看完整版|