其實這完全取決於編譯器。只需要爲其輸入生成正確的代碼。爲了這樣做,它必須遵循C++標準,因爲這解釋了什麼是是正確的。在這種情況下,它表示編譯器必須在進程的一個步驟中將具有不同參數的模板實例化爲不同類型,這些類型稍後可以由相同的代碼表示,或者不是,它完全取決於編譯器。
編譯器很可能會內聯至少MaxLength(),但也可能是你的ctor。否則,它可能很好地生成你的ctor的一個實例,並通過/讓它從別處檢索S.要知道的唯一方法是檢查編譯器的輸出。
因此,爲了確切知道我決定列出VS2005在發佈版本中所做的工作。我編寫的文件是這樣的:
template <int S>
class 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());
}
彙編器輸出如下:
[email protected]@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 [email protected]@[email protected][email protected]@[email protected] ; useA
正如你可以看到兩個構造函數和調用的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 [email protected]@[email protected][email protected]@@[email protected] ; useA
這是非常有趣的,看看聰明的方式編譯器優化的循環。對於那些使用memset()的所有那些過早的優化器,我會說你傻瓜。
如果將A和Maxlength的定義移動到不同的cpp文件,它將如何工作。
它可能不會編譯(除非你只在該cpp文件中使用A)。
不完全。編譯器需要爲每個S值生成一個單獨的類型。如果編譯器認爲它是安全的,它當然可以通過將多個實例合併回來或內聯來優化。但是,標準要求它們被視爲獨立的類型。 – jalf 2008-12-08 16:28:14