您的位置:首页 > 其它

模板的类型萃取

2017-11-22 23:17 288 查看
分析类型萃取问题

功能:

类型萃取,在STL中用到的比较多,用于判断一个变量是否为POD(plain old data,平凡类型)类型。

简单来说可以用来判断出某个变量是内置类型还是自定义类型。

通过类型萃取,萃取到变量类型,对不同变量进行不同处理,可以提升程序效率。

应用场景:

例如实现顺序表,在对顺序表进行扩容时,利用类型萃取,重新开辟内存、拷贝对象。

拷贝对象时,分两种情况:1)内置类型,如int、char……;2)自定义类型,如Date类、SeqList类。

对于内置类型,可通过memcpy函数进行拷贝,此时进行的是浅拷贝。

而,对于自定义类型,大多数需要深拷贝的对象来说,必须调用赋值语句来赋值。

因此,在拷贝对象时,为不出错,通常用赋值语句来赋值。但缺点是效率较低。

通过类型萃取判断POD类或非POD类,对于POD类用浅拷贝,memcpy函数,对于非POD类用深拷贝,进行赋 值,这样就可以提高程序效率。

实现:

类型萃取,在技术层面,就是利用了模板的特化。

下面举例说明:

template<class T>
void SeqList::CheckCapacity()
{
_capacity=_capacity>0?_capacity*2:3;
T* tmp=new T[_capacity];
if(_a)
{
memecpy(tmp,_a,sizof(T)*_size);
delete[] _a;
}
_a=tmp;
}


代码中,当T为内置类型时,可以正常运行,但当T为自定义类型时会出错,原因是memcpy是浅拷贝,自定义类型中如果有指针,当扩容前存了指针ptr进去,使用CheckCapacity()扩容时,delete[] _a会清理释放ptr指向的内容,当使用memcpy函数进行浅拷贝后,扩容后的ptr为野指针,当程序执行结束时会调用析构函数,那么将会对同一块空间析构两次。





类型萃取的代码如下:

template<class T>
struct _TypeTraits
{
//POD——基本类型,指在C++中与C兼容的类型,可以按照C的方式处理。
typedef _FalseType IsPODType;
};
template<>
struct _TypeTraits<int>//特化
{
typedef _TrueType IsPODType;
};

template<class T>
T* TypeCopy(T* dst, const T* src, size_t n)
{
return _TypeCopy(dst, src, n, _TypeTraits<T>::IsPODType());
};
template<class T>
T* _TypeCopy(T* dst, const T* src, size_t n, _FalseType)
{
T* Dst = dst;
for (size_t i = 0; i<n; ++i)
{
dst[i] = src[i];
}
return Dst;
};
template<class T>
T* _TypeCopy(T* dst, const T* src, size_t n, _TrueType)
{
return (T*)memcpy(dst, src, n*sizeof(T));
};


测试代码如下:

void Test()
{
int a1[3] = { 1, 2, 3 };
int a2[3];
char s1[]="aabbcc";
char s2[7];
TypeCopy(a2, a1, 3);
TypeCopy(s2, s1, 7);
for (size_t i = 0; i<3; ++i)
{
cout << a2[i] << " ";
}
cout << endl;
for (size_t i = 0; i<7; ++i)
{
cout << s2[i] << " ";
}
cout << endl;
}
int main()
{
Test();
system("pause");
return 0;
}


运行结果:



分析图如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: