构造和析构的基本工具
1.construct
对placement new包装
// 包装 placement new
template<typename T1, typename T2>
inline void construct(T1* p, const T2& val)
{
new (p) T1(val);
}
// 无参的
template<typename T>
inline void construct(T* p)
{
new (p) T();
}
有了这两个函数,就可以使用construct来对指定位置构造值。
示例:
int main(void)
{
int* p = (int*)malloc(sizeof(int));
Srh::construct(p, 100);
cout << *p << endl;
return 0;
}
2. destroy
2.1普通版本
两个版本,一个是对单个对象析构,一个是对迭代器范围内的对象析构。
那么就有这样一个问题,如果这迭代器范围内的对象,其析构过程是无关紧要的,那么这样编写就会影响效率。
// 析构对象
template<typename T>
inline void destroy(T* p)
{
p->~T();
}
// 析构范围内的对象
template<typename _FI>
inline void destroy(_FI _F, _FI _L)
{
for (; _F != _L; ++F)
{
destroy(&*_F);
//(*_F)表示迭代器所指之物,
// (&*_F)表示迭代器所指之物的地址
}
}
2.2 类型萃取版本
通过类型萃取来看要析构的对象是否是无关紧要的。
流程:
- 调用 destroy(),通过value_type(_F)来获取迭代器所指之物的类型。
- __destroy()来得知T的值类型的析构函数是否是无关紧要的。
- 如果为真,那么就调用下面第一个函数,什么都不执行。
- 如果为假,就调用第二个函数,对迭代器范围内的对象析构。
// 如果析构函数无关紧要,那么就不需要上面这样麻烦
// 那么利用上面已知的true/false来判断
template<typename _FI>
inline void __destroy_aux(_FI _F, _FI _L, Srh::__true_type)
{}
template<typename _FI>
inline void __destroy_aux(_FI _F, _FI _L, Srh::__false_type)
{
for (; _F != _L; ++_F)
{
destroy(&*_F);
}
}
template<typename _FI, typename T>
inline void __destroy(_FI _F, _FI _L, T*)
{
// 得知T所指之物的值类型
// 再根据类型萃取 获取 值类型的析构函数是 true还是false
typedef typename Srh::__type_traits<T>::has_trivial_destructor dest;
__destroy_aux(_F, _L, dest());
}
template<typename _FI>
inline void destroy(_FI _F, _FI _L)
{
// 调用下面的__destroy,获取_F迭代器所指之物的类型
__destroy(_F, _L, Srh::value_type(_F));
}
示例:
class Object
{
private:
int value;
public:
Object(int x = 0) : value(x) {
cout << "Object::create: " << value << endl;
}
~Object() {
cout << "Object::destroy" << endl;
}
};
int main(void)
{
const int n = 10;
Object* op = (Object*)malloc(sizeof(Object) * n);
for (int i = 0; i < n; ++i)
{
Srh::construct(&op[i], i);
}
Srh::destroy(op, op + n);
free(op);
return 0;
}
运行结果
原因是在type_traits中,对设计的类型的析构函数都是有关紧要的。
struct __true_type {};
struct __false_type {};
template<typename type>
struct __type_traits
{
typedef __true_type this_dummy_member_must_be_first;
typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_copy_constructor;
typedef __false_type has_trivial_assignment_operator;
// 有关紧要的
typedef __false_type has_trivial_destructor;
typedef __false_type is_POD_type;
};
因此,可以对其提供一个特化版本:
template<>
struct Srh::__type_traits<Object>
{
__type_traits() {}
typedef __false_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
并在destroy函数里打印T的类型,方便得知是什么类型调用该函数。
template<typename _FI, typename T>
inline void __destroy(_FI _F, _FI _L, T*)
{
cout << typeid(T).name() << endl;
Srh::__type_traits<T>();
typedef typename Srh::__type_traits<T>::has_trivial_destructor dest;
__destroy_aux(_F, _L, dest());
}
运行结果:
源代码
#ifndef MY_CONSTRUCT_H
#define MY_CONSTRUCT_H
#include"my_iterator.h"
#include"my_type_traits.h"
namespace Srh
{
// 包装定位new placement new
template<typename T1, typename T2>
inline void construct(T1* p, const T2& val)
{
new (p) T1(val);
}
// 无参的
template<typename T>
inline void construct(T* p)
{
new (p) T();
}
// 析构对象
template<typename T>
inline void destroy(T* p)
{
p->~T();
}
/*
// 析构范围内的对象
template<typename _FI>
inline void destroy(_FI _F, _FI _L)
{
for (; _F != _L; ++F)
{
destroy(&*_F);
//(*_F)表示迭代器所指之物,
// (&*_F)表示迭代器所指之物的地址
}
}
*/
// 如果析构函数无关紧要,那么就不需要上面这样麻烦
// 那么利用上面已知的true/false来判断
template<typename _FI>
inline void __destroy_aux(_FI _F, _FI _L, Srh::__true_type)
{}
template<typename _FI>
inline void __destroy_aux(_FI _F, _FI _L, Srh::__false_type)
{
for (; _F != _L; ++_F)
{
destroy(&*_F);
}
}
template<typename _FI, typename T>
inline void __destroy(_FI _F, _FI _L, T*)
{
// 得知T所指之物的值类型
// 再根据类型萃取 获取 值类型的析构函数是 true还是false
typedef typename Srh::__type_traits<T>::has_trivial_destructor dest;
__destroy_aux(_F, _L, dest());
}
template<typename _FI>
inline void destroy(_FI _F, _FI _L)
{
// 调用下面的__destroy,获取_F迭代器所指之物的类型
__destroy(_F, _L, Srh::value_type(_F));
}
}
#endif