Home  >  Q&A  >  body text

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

有一个模板函数

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

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

T tmp

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

迷茫迷茫2715 days ago636

reply all(3)I'll reply

  • 大家讲道理

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

    Uniform initialization for c++11:

    T tmp {};

    Before you should be able to write:

    T tmp = T();

    reply
    0
  • 高洛峰

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

    @Shihira

    template <typename T,bool>
    struct init_obj{
    
        T operator()(int value) {
            return T(value);
        }
    
    };
    
    template<typename T>
    struct init_obj<T,false> {
        T operator()(int value) {
            return T{};
        }
    };
    
    template<typename T>
    T rt(int value) {
    
        return init_obj<T, is_convertible<T, int>::value>()(value);
    }

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-17 15:27:21

    I understand what the questioner means is that if it can be initialized with 0 as a parameter, try to initialize it with 0, and if it doesn't work, use the default constructor.

    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
    }

    There are several points here. One is that it cannot be T tmp directly, because the Scalar Type will not be initialized and will directly use the garbage data in the stack, so that its data is not 0. Second, you cannot use the C method memset, because C++ objects are often constructed by default to allocate memory. If the pointer is set to zero, a segmentation fault or memory leak will occur. Third, because an object is returned directly, performance may be reduced if T does not have a move constructor.

    The principle of the above writing method is this. Taking advantage of the difference between Int and int, because C++ will give priority to more specialized functions (or overloaded functions) when making template decisions, the following init_obj takes precedence over the above one. Enable is used to generate derivation errors for types that cannot be initialized with 0. C++'s SFINAE policy transfers it to the above one init_obj; 0.f is used here because integer types will be implicitly converted to pointers, but float will not, And float can be implicitly converted to any numeric type.

    Personally, I think my writing is ugly and I’d like to ask for a better way of writing (

    For C++11, the writing method above is great:)

    reply
    0
  • Cancelreply