我有一个类似下面的模板类.
templateclass A { private: char string[S]; public: A() { for(int i =0; i 如果我使用不同的S值实例化上述类,编译器是否会创建A()和MaxLenth()函数的不同实例?或者它会创建一个实例并将S作为某种参数传递?
如果我将A和Maxlength的定义移动到不同的cpp文件,它将如何表现.
1> Alastair..:将针对S的每个不同值实例化模板.
如果将方法实现移动到其他文件,则需要#include该文件.(例如,Boost使用
.ipp
需要#included的源文件的约定).如果您想最小化使用模板实例化生成的代码量(因此需要在
.ipp
文件中提供),您应该尝试通过删除对S的依赖性来将其分解.例如,您可以从(私有)基类,它以S作为参数提供成员函数.
2> Andreas Magn..:实际上这完全取决于编译器.它只需要为其输入生成正确的代码.为了做到这一点,它必须遵循C++标准,因为它解释了什么是正确的.在这种情况下,它表示编译器必须在流程的一个步骤实例化具有不同参数的模板作为不同的类型,这些类型以后可能由相同的代码表示,或者不是,它完全取决于编译器.
编译器最有可能至少内联MaxLength(),但也可能是你的ctor.否则它可能很好地生成你的ctor的单个实例并传递/让它从其他地方检索S. 确切知道的唯一方法是检查编译器的输出.
因此,为了确定我已经决定列出VS2005在发布版本中的功能.我编译的文件如下所示:
templateclass A { char s_[S]; public: A() { for(int i = 0; i < S; ++i) { s_[i] = 'A'; } } int MaxLength() const { return S; } }; extern void useA(A<5> &a, int n); // to fool the optimizer extern void useA(A<25> &a, int n); void test() { A<5> a5; useA(a5, a5.MaxLength()); A<25> a25; useA(a25, a25.MaxLength()); } 汇编程序输出如下:
?test@@YAXXZ PROC ; test, COMDAT [snip] ; 25 : A<5> a5; mov eax, 1094795585 ; 41414141H mov DWORD PTR _a5$[esp+40], eax mov BYTE PTR _a5$[esp+44], al ; 26 : useA(a5, a5.MaxLength()); lea eax, DWORD PTR _a5$[esp+40] push 5 push eax call ?useA@@YAXAAV?$A@$04@@H@Z ; useA正如您所看到的那样,ctor和对MaxLength()的调用都是内联的.正如您现在可能猜测它与A <25>类型相同:
; 28 : A<25> a25; mov eax, 1094795585 ; 41414141H ; 29 : useA(a25, a25.MaxLength()); lea ecx, DWORD PTR _a25$[esp+48] push 25 ; 00000019H push ecx mov DWORD PTR _a25$[esp+56], eax mov DWORD PTR _a25$[esp+60], eax mov DWORD PTR _a25$[esp+64], eax mov DWORD PTR _a25$[esp+68], eax mov DWORD PTR _a25$[esp+72], eax mov DWORD PTR _a25$[esp+76], eax mov BYTE PTR _a25$[esp+80], al call ?useA@@YAXAAV?$A@$0BJ@@@H@Z ; useA看到编译器优化for循环的聪明方法非常有趣.对于那些使用memset()的那些过早优化器,我会对你说傻瓜.
如果我将A和Maxlength的定义移动到不同的cpp文件,它将如何表现.
它可能无法编译(除非您只在该cpp文件中使用A).