搜尋

首頁  >  問答  >  主體

C++模板函数中临时变量初始化问题

有一个模板函数

template<typename T>
void function(T num){
    T tmp;
    memset(&tmp,0,sizeof(tmp));    //现在我是这么初始化的
}

然后我需要在函数里定义一个临时变量

T tmp

但这个T有可能是类类型(string), 也可能是内建类型(int, double)
那我要怎么初始化?
现在我是用memset()初始化的;
但如果sum这对象不在一块连续内存或者他定义时会初始化一些特殊成员, 这种方法就不行...

迷茫迷茫2807 天前714

全部回覆(3)我來回復

  • 大家讲道理

    大家讲道理2017-04-17 15:27:21

    c++11的統一初始化:

    T tmp {};

    以前應該可以寫:

    T tmp = T();

    回覆
    0
  • 高洛峰

    高洛峰2017-04-17 15:27:21

    @Shihira

    呃呃

    回覆
    0
  • 天蓬老师

    天蓬老师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的場合,樓上的寫法是很棒的:)

    回覆
    0
  • 取消回覆