在前面的課程中,我們了解了函數模闆的定義和使用方法,并知道它在被調用的時候,會根據傳進的模闆參數生成一個模闆函數,模闆函數是函數模闆的具現。函數模闆是模闆函數的抽象。
大家都知道,在C++的函數中可以定義一個靜态局部變量,這個靜态局部變量的生命周期同整個程式的生命周期相同,但是隻有在第一次調用定義這個靜态局部變量的函數的時候,才會初始化這個靜态局部變量,之後的調用就不會在對它進行初始化。
例1中的代碼證明了上述的觀點,如下:
例1 函數中的靜态局部變量隻被初始化一次
#include<iostream>
using namespace std;
void PrintStaticVar()
{
static int a = 0;
a++;
cout << "static var:" << a << endl;
}
void main()
{
PrintStaticVar();
PrintStaticVar();
PrintStaticVar();
}
運作效果如圖1所示:

圖1 函數中的靜态局部變量隻被初始化一次
通過實踐證明,例1中的靜态局部變量a隻被初始化了一次。
在上面的例子中,我們講述了普通函數的靜态局部變量的初始化。那麼對于函數模闆中的靜态局部變量是怎麼初始化的?它的規則如下:
1、函數模闆會根據不同的模闆參數生成不同的模闆函數
2、每一個模闆函數中的靜态局部變量隻被初始化一次
下面,我們通過例2中的代碼來證明上述的規則。
例2 規則證明
#include<iostream>
using namespace std;
template<typename T1, typename T2>
void PrintTemplateStaticVar(T1 a, T2 b)
{
static int nTemp = 0;
nTemp++;
cout << "type:"<<sizeof(a)<<"template static var:" << nTemp << endl;
return ;
}
int main()
{
PrintTemplateStaticVar<int, int>(1, 2);
PrintTemplateStaticVar<int, int>(3, 4);
PrintTemplateStaticVar<int, int>(5, 6);
PrintTemplateStaticVar<double, double>(1, 2);
PrintTemplateStaticVar<double, double>(3, 4);
PrintTemplateStaticVar<double, double>(5, 6);
return 0;
}
運作效果如圖2所示:
圖2 規則證明
在例2中,我們首先定義了一個函數模闆PrintTemplateStaticVar,在這個函數模闆中,我們又定義了一個靜态變量nTemp,之後就是在每次調用這個函數的時候,列印靜态變量的值。
通過實踐證明,當我們多次調用同一個模闆函數的時候,它的靜态變量隻在第一次調用時被初始化。比如,在例2中,我們三次調用了模闆函數PrintTemplateStaticVar<int, int>,但是它的靜态變量隻被初始化了一次。同理我們又三次調用了模闆函數PrintTemplateStaticVar<double, double>,它的靜态變量也是在第一次調用被初始化,并且模闆函數PrintTemplateStaticVar<int, int>和模闆函數PrintTemplateStaticVar<double, double>的靜态變量不是同一個。
使用nm和grep指令擷取的函數資訊如下:
圖3 兩個模闆函數和兩個靜态變量