今天和同事说到C++模板会使代码膨胀, 可同事觉得不会。
同事的依据是: 如果模板会使代码膨胀, 那么ATL和WTL里为什么还要大量使用模板? 同样功能 ,ATL和WTL编译出的可执行文件可比MFC编译的要小的多。
我当时一愣 ,事实确实如同事所说,难道模板会使代码膨胀的观点是错误的吗?
MFC因为本身代码量和复杂性在那里, 所以它生成比较大的exe无可厚非。我们这里重点关注为什么ATL/WTL使用模板,但是却不会使生成的exe变大。
我们知道使用模板时, 同一模板生成不同的模板实类后会是多份代码 ,比如 vector<int>, vector<char>, vector<double>, 这里总共会生成3份不同的vector代码,这就是我们平时所说的代码膨胀。
那么为什么ATL/WTL就没有代码膨胀的问题呢?
我这里以 ATL里的窗口代码为例来分析这个问题,因为我对WinDbg比较熟悉,下面我会以WinDbg为工具来分析我以前的写得那个俄罗斯方块程序。
首先我们看一下ATL的窗口代码:
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);
}
};
</div>
上面是一个模板类,它应该会生成多份模板实例代码:我们可以用WinDbg的符号搜索命令来做验证:
输入 x HYTeris!ATL::CWindowImpl<* , 搜索所有以 HYTeris!ATL::CWindowImpl< 开头的符号
0045f640 HYTeris!ATL::CWindowImpl<CTsUserListCtrl,WTL::CListViewCtrlT<ATL::CWindow>,ATL::CWinTraitsOR<32777,0,ATL::CWinTraits<14428