C++模板会使代码膨胀吗(一)

2014-11-24 09:13:57 · 作者: · 浏览: 8

今天和同事说到C++模板会使代码膨胀, 可同事觉得不会。
同事的依据是: 如果模板会使代码膨胀, 那么ATL和WTL里为什么还要大量使用模板 同样功能 ,ATL和WTL编译出的可执行文件可比MFC编译的要小的多。
我当时一愣 ,事实确实如同事所说,难道模板会使代码膨胀的观点是错误的吗

MFC因为本身代码量和复杂性在那里, 所以它生成比较大的exe无可厚非。我们这里重点关注为什么ATL/WTL使用模板,但是却不会使生成的exe变大。www.2cto.com

我们知道使用模板时, 同一模板生成不同的模板实类后会是多份代码 ,比如 vector, vector, vector, 这里总共会生成3份不同的vector代码,这就是我们平时所说的代码膨胀。

那么为什么ATL/WTL就没有代码膨胀的问题呢
我这里以 ATL里的窗口代码为例来分析这个问题,因为我对WinDbg比较熟悉,下面我会以WinDbg为工具来分析我以前的写得那个俄罗斯方块程序。

首先我们看一下ATL的窗口代码:
template
class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits >
{
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< TBase, TWinTraits >::Create(hWndParent, rect, szWindowName,
dwStyle, dwExStyle, MenuOrID, atom, lpCreateParam);
}
};
上面是一个模板类,它应该会生成多份模板实例代码:我们可以用WinDbg的符号搜索命令来做验证:
输入 x HYTeris!ATL::CWindowImpl<* , 搜索所有以 HYTeris!ATL::CWindowImpl< 开头的符号
0:000> x HYTeris!ATL::CWindowImpl<*
004592f0 HYTeris!ATL::CWindowImpl,ATL::CWinTraits<1442840576,0> >::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<1442840576,0> >::~CWindowImpl,ATL::CWinTraits<1442840576,0> > (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<1442840576,0> >::CWindowImpl,ATL::CWinTraits<1442840576,0> > (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<1442840576,0> >::CWindowImpl,ATL::CWinTraits<1442840576,0> > (void)
0040ea20 HYTeris!ATL::CWindowImpl >::Create (struct HWND__ *, class ATL