天天看點

模闆函數的靜态變量

    在前面的課程中,我們了解了函數模闆的定義和使用方法,并知道它在被調用的時候,會根據傳進的模闆參數生成一個模闆函數,模闆函數是函數模闆的具現。函數模闆是模闆函數的抽象。

    大家都知道,在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 兩個模闆函數和兩個靜态變量