C++ STL : 空间配置器——构造和析构的基本工具construct和destroy

12 篇文章 1 订阅

构造和析构的基本工具

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 类型萃取版本

通过类型萃取来看要析构的对象是否是无关紧要的。

流程:

  1. 调用 destroy(),通过value_type(_F)来获取迭代器所指之物的类型。
  2. __destroy()来得知T的值类型的析构函数是否是无关紧要的。
  3. 如果为真,那么就调用下面第一个函数,什么都不执行。
  4. 如果为假,就调用第二个函数,对迭代器范围内的对象析构。
// 如果析构函数无关紧要,那么就不需要上面这样麻烦
// 那么利用上面已知的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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_索伦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值