有一个模板函数
template<typename T>
void function(T num){
T tmp;
memset(&tmp,0,sizeof(tmp)); //现在我是这么初始化的
}
然后我需要在函数里定义一个临时变量
T tmp
但这个T有可能是类类型(string), 也可能是内建类型(int, double)
那我要怎么初始化?
现在我是用memset()初始化的;
但如果sum这对象不在一块连续内存或者他定义时会初始化一些特殊成员, 这种方法就不行...
天蓬老师2017-04-17 15:27:21
我理解題主的意思是能用0這個參數初始化的就盡量用0初始化,其它不行的就用預設構造函數。
template<typename T, typename Int = int>
T init_obj(Int) {
return T{};
};
template<typename T, typename Enable = decltype(T(0.f))>
T init_obj(int) {
return T(0);
};
int main()
{
int i = init_obj<int>(0);
float f = init_obj<float>(0);
string s = init_obj<string>(0);
vector<int> v = init_obj<vector<int>>(0);
cout << i << endl; // 0
cout << f << endl; // 0
cout << s << endl; //
cout << v.size() << endl; // 0
}
這裡有幾個點,一個是不能直接T tmp
,因為Scalar Type會不初始化以至於直接使用棧當中的垃圾數據,以至於其數據不是0。二是不能用memset
這種C的方法,因為C++的物件很多時候預設構造會分配內存,如果把指標置零會產生段錯誤或記憶體洩漏。三是這裡因為直接回傳一個對象,如果T沒有移動構造函數可能會降低效能。
上面這個寫法的原理是這樣的。利用Int和int的差別,因為C++在模板決策的時候會優先選擇特化程度更高的函數(或曰重載過的函數),所以下面一個init_obj
比上面的更優先。 Enable用於對不能用0初始化的型別產生推導錯誤,C++的SFINAE政策將其轉移到上面一個init_obj
;這裡用0.f
是因為整型類型會隱式轉換到指針,但是float不會,而float也可以隱式轉換到任意一種數字類型。
個人覺得自己寫得很難看,求更好的寫法(
C++11的場合,樓上的寫法是很棒的:)