Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Construct.h 中的 void destroy(ForwardIterator, ForwardIterator) 有点疑惑 #24

Open
ghost opened this issue Aug 9, 2017 · 5 comments

Comments

@ghost
Copy link

ghost commented Aug 9, 2017

这个函数是这样的:

1  template<class ForwardIterator>
2  inline void destroy(ForwardIterator first, ForwardIterator last) {
3	typedef typename _type_traits<ForwardIterator>::is_POD_type is_POD_type;
4	_destroy(first, last, is_POD_type());
5  }

第 3 句用了 _type_traits <ForwardIterator>::is_POD_type

这个版本的 destroy 对于 POD 类型不调用析构函数,对于非POD类型则调用析构函数。

假设类型 T 是 一个 ForwardIterator 的 value_type,那么通过这个 ForwardIterator 的类型判断可以决定 T 是 否为 POD 类型吗?

@gitforhzc
Copy link

假设ForwardIterator为char,那么_type_traits <ForwardIterator>::is_POD_type为_true_type。
详见TypeTraits.h

	template<>
	struct _type_traits<char>
	{
		typedef _true_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;
	};

@ghost
Copy link
Author

ghost commented Aug 15, 2017

欢迎探讨。

恐怕我的问题表述不清,我再说一下。

我的疑问是:destroy() 这个函数模板,它为了更高效地析构 [first, last) 内的元素,需要对迭代器所指的元素类型进行分类,于是应该以萃取的方式得到元素类型。

_type_traits <ForwardIterator>::is_POD_type ,这句是通过判断迭代器的类型来决定是否调用析构函数。

当 is_POD_type() 为 true_type 和 false_type 时分别执行下列函数模板:

// true_type
template<class ForwardIterator>
inline void _destroy(ForwardIterator first, ForwardIterator last, _true_type){}

// false_type
template<class ForwardIterator>
inline void _destroy(ForwardIterator first, ForwardIterator last, _false_type){
	for (; first != last; ++first){
		destroy(&*first);
	}
}

那么通过迭代器类型来决定是否调用析构函数合理吗?

举个例子,对于 forward_list<int> 来说,其 value_type 为 int(POD ),有 trivial destructor,不需要额外的操作;而通过判断 forward_list<int>::iterator 的类型(non-POD),则需要调用析构函数。

测试代码如下:

#include <type_traits>
#include <forward_list>
#include <iostream>

int main()
{
  std::cout << std::boolalpha;

  std::cout << "std::is_pod<int>::value = ";
  std::cout << std::is_pod<int>::value << std::endl;
  
  std::cout << "std::is_pod<std::forward_list<int>::iterator>::value = ";
  std::cout << std::is_pod<std::forward_list<int>::iterator>::value;

  return 0;
}

运行结果:

std::is_pod<int>::value = true
std::is_pod<std::forward_list<int>::iterator>::value = false

@gitforhzc
Copy link

你说得对。这是原作者的练手项目,并不是很严谨。
《STL源码剖析》2.2.3节是这么处理的:

template <class ForwardIterator> 
inline void destroy(ForwardIterator first, ForwardIterator last)
{
  __destroy(first, last, value_type(first)); 
}
// 判断元素的数值类型(value type)是否有trivial destructor
template <class ForwardIterator, class T>
inline void __destroy(ForwardIterator first, ForwardIterator last, T*)
{
  typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;
  __destroy_aux(first, last, trivial_destructor());
}
//如果元素的数值类型(value type)有non-trivial destructor...
template <class ForwardIterator>
inline void __destroy_aux(ForwardIterator first, ForwardIterator last, __false_type)
{
  for (; first < last; ++first)
    destroy(&*first);
}

建议对照《STL源码剖析》批判着学。

@ghost
Copy link
Author

ghost commented Aug 15, 2017

嗯,谢谢建议。

其实我也正在根据 SGI STL 造自己的轻量 STL,而作者的 TinySTL 给了我最初的造轮子的勇气和想法;瑕不掩瑜,作者的完成度还是很高的。

@liuziangexit
Copy link

学习了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants