1.使用memcpy拷贝
template<class T>
void Copy(T* dst, const T* src, size_t size)
{
memcpy(dst, src, sizeof(T)*size);
}
int main()
{
// 试试下面的代码
std::string strarr1[3] = { "11", "22", "33" };
std::string strarr2[3];
Copy(strarr2, strarr1, 3);
return 0;
}
上述代码虽然对于任意类型的空间都可以进行拷贝,但是如果拷贝自定义类型对象就可能会出错,因为自定义类型对象有可能会涉及到深拷贝(比如string),而memcpy属于浅拷贝(若拷贝的资源内有指针,则拷贝的是地址而不是指针所指向的资源)。如果对象中涉及到资源管理,就只能用赋值。
2 使用赋值方式拷贝
缺点:循环赋值的方式虽然可以,但是代码的效率比较低
template<class T>
void Copy(T* dst, const T* src, size_t size)
{
for(size_t i = 0; i < size; ++i)
{
dst[i] = src[i];
}
}
3. 增加bool类型区分自定义与内置类型
template<class T>
void Copy(T* dst, const T* src, size_t size, bool IsPODType)
{
if(IsPODType)
memcpy(dst, src, sizeof(T)*size);
else
{
for(size_t i = 0; i < size; ++i)
dst[i] = src[i];
}
}
缺点:用户需要根据所拷贝元素的类型去传递第三个参数,那出错的可能性就增加。
4.类型萃取
//为了将内置类型与自定义类型区分开,给出以下两个类分别代表内置类型与自定义类型。
// 代表内置类型
struct TrueType
{
static bool Get()
{
return true;
}
};
// 代表自定义类型
struct FalseType
{
static bool Get()
{
return false;
}
};
//给出以下类模板,将来用户可以按照任意类型实例化该类模板。
template<class T>
struct TypeTraits
{
typedef FalseType IsPODType;
};
//对上述的类模板进行以下方式的实例化
template<>
struct TypeTraits<char>
{
typedef TrueType IsPODType;
};
template<>
struct TypeTraits<short>
{
typedef TrueType IsPODType;
};
template<>
struct TypeTraits<int>
{
typedef TrueType IsPODType;
};
template<>
struct TypeTraits<long>
{
typedef TrueType IsPODType;
};
template<>
struct TypeTraits<long long>
{
typedef TrueType IsPODType;
};
template<>
struct TypeTraits<long double>
{
typedef TrueType IsPODType;
};
template<>
struct TypeTraits<float>
{
typedef TrueType IsPODType;
};
template<>
struct TypeTraits<double>
{
typedef TrueType IsPODType;
};
template<class T>
void Copy(T* dst, const T* src, size_t size)
{
if (TypeTraits<T>::IsPODType::Get())
memcpy(dst, src, sizeof(T)*size);
else
{
for (size_t i = 0; i < size; ++i)
dst[i] = src[i];
}
}
int main()
{
int a1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int a2[10];
Copy(a2, a1, 10); //调用memcpy
string s1[] = { "1111", "2222", "3333", "4444" };
string s2[4];
Copy(s2, s1, 4); //执行for循环
return 0;
}
拓展:STL中类型萃取的例子
①注意:在重载内置类型时,所有的内置类型都必须重载出来,包括有符号和无符号,比如:对于int类型,必须特化三个,int – signed int – unsigned int
②在需要区分内置类型与自定义类型的位置,标准库通常都是通过__true_type与__false_type给出一对重载的函数,然后用一个通用函数对其进行封装
③注意:第四个参数可以不提供名字,该参数最主要的作用就是让两个_copy函数形成重载
// 代表内置类型
struct __true_type {};
// 代表自定义类型
struct __false_type {};
template <class type>
struct __type_traits
{
typedef __false_type is_POD_type;
};
// 对所有内置类型进行特化
template<>
struct __type_traits<char>
{
typedef __true_type is_POD_type;
};
...........这里就只举一个char的例子
template<class T>
void _copy(T* dst, T* src, size_t n, __true_type)
{
memcpy(dst, src, n*sizeof(T));
}
template<class T>
void _copy(T* dst, T* src, size_t n, __false_type)
{
for (size_t i = 0; i < n; ++i)
dst[i] = src[i];
}
template<class T>
void Copy(T* dst, T* src, size_t n)
{
_copy(dst, src, n, __type_traits<T>::is_POD_type());
}