MyTinySTL阅读笔记---迭代器

迭代器

概述

迭代器提供一种方法使它能够依顺序访问聚合物(容器)所含的各个元素,而又无需暴露改聚合物的内部表述方式。
迭代器可被用来访问一个容器类的所包函的全部元素,其行为像一个指针(对operator *和operator->进行重载)。

在这里插入图片描述
设计算法时,如果可能,尽量针对某种特定迭代器提供一个明确定义,并针对更强化的某种迭代器提供另一种定义,这样能在不同情况下提供最大效率。

class与typename的区别

  1. typename和class在作为参数类型时用法一样, 没有区别
  2. typename主要用于对嵌套依赖类型进行提取(萃取). 而class没有这样的功能.
  3. typename提取的一个例外是在继承或成员初始化列表中对基类进行初始化时不用加typename关键字

类型

根据移动特性和实施操作被分为5类:

  1. input iterator(输入迭代器) : 迭代器所指的内容不能被修改, 只读且只能执行一次读操作.
  2. output iterator(输出迭代器) : 只写并且一次只能执行一次写操作.
  3. forward iterator(正向迭代器) : 支持读写操作且支持多次读写操作.
  4. bidirectional iterator(双向迭代器) : 支持双向的移动且支持多次读写操作.
  5. random access iterator(随机访问迭代器) : 支持双向移动且支持多次读写操作. p+n, p-n等.
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};

这五个类都是空类, 只是为了之后调用时通过类选择不同的重载函数。继承是为了可以使用传递调用,当不存在某种迭代器类型匹配时编译器会依据继承层次向上查找进行传递, 就可以通过继承关系来决定选择最优的调用。

任何迭代器都应该提供五个内嵌相应类型(使用typename对参数类型的提取(萃取), 并且对参数类型在进行一次命名, 看上去对参数类型的使用有了一层间接性。):

// iterator 模板
// 为了避免写代码的时候遗漏,最好继承此类
template <class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T&>
struct iterator
{
  typedef Category              iterator_category;	// 迭代器类型
  typedef T                     value_type;			// 迭代器所指对象类型
  typedef Pointer               pointer;			// 迭代器所指对象的类型指针
  typedef Reference             reference;			// 迭代器所指对象的类型引用
  typedef Distance              difference_type;	// 两个迭代器之间的距离
};

五类迭代器:

template <class T, class Distance>
struct input_iterator 
{
  	typedef input_iterator_tag iterator_category;
  	typedef T                  value_type;
  	typedef Distance           difference_type;
  	typedef T*                 pointer;
  	typedef T&                 reference;
};

struct output_iterator
{
  typedef output_iterator_tag iterator_category;
  typedef void                value_type;
  typedef void                difference_type;
  typedef void                pointer;
  typedef void                reference;
};

template <class T, class Distance>
struct forward_iterator
{
  typedef forward_iterator_tag iterator_category;
  typedef T                    value_type;
  typedef Distance             difference_type;
  typedef T*                   pointer;
  typedef T&                   reference;
};

template <class T, class Distance>
struct bidirectional_iterator
{
  typedef bidirectional_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef Distance                   difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};

template <class T, class Distance>
struct random_access_iterator
{
  typedef random_access_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef Distance                   difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};

萃取迭代器(不管是函数返回值类型还是原生指针都能通过萃取器萃取出来, typename I::类型进行类型萃取。原生指针不能内嵌型别声明,所以内嵌型别在这里不适用, 迭代器无法表示原生指针(int *, char *等称为原生指针)。 这个问题就通过traits偏特化技术解决的。):

// 萃取迭代器类型
template <class Iterator>
struct iterator_traits
{
  typedef typename Iterator::iterator_category iterator_category;	// 迭代器类型
  typedef typename Iterator::value_type        value_type;			// 迭代器所指对象的类型
  typedef typename Iterator::difference_type   difference_type;		// 两个迭代器之间的距离
  typedef typename Iterator::pointer           pointer;				// 迭代器所指对象的类型指针
  typedef typename Iterator::reference         reference;			// 迭代器所指对象的类型引用
};
// 针对原生指针 T* 生成的 traits 偏特化
template <class T>
struct iterator_traits<T*>
{
  typedef random_access_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef ptrdiff_t                  difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};
// 针对原生指针 const T* 生成的 traits 偏特化
template <class T>
struct iterator_traits<const T*>
{
  typedef random_access_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef ptrdiff_t                  difference_type;
  typedef const T*                   pointer;
  typedef const T&                   reference;
};


// 这个函数可以很方便的决定某个迭代器的类型
template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&)
{
  typedef typename iterator_traits<Iterator>::iterator_category category;
  return category();
}

// 这个函数可以很方便的决定某个迭代器的距离类型
template <class Iterator>
inline typename iterator_traits<Iterator>::difference_type*
distance_type(const Iterator&)
{
  return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);
}

// 这个函数可以很方便的决定某个迭代器所指对象的类型
template <class Iterator>
inline typename iterator_traits<Iterator>::value_type*
value_type(const Iterator&)
{
  return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
}

通过萃取迭代器信息进行分类处理例子:

template <class InputIterator, class Distance>
inline void distance(InputIterator first, InputIterator last, Distance& n) 
{
  	__distance(first, last, n, iterator_category(first));
}

// 对input_iterator_tag需要遍历才能计算出距离
template <class InputIterator, class Distance>
inline void __distance(InputIterator first, InputIterator last, Distance& n, input_iterator_tag) 
{
  	while (first != last) 
    { ++first; ++n; }
}

// 对random_access_iterator_tag像指针一样计算就可以了
template <class RandomAccessIterator, class Distance>
inline void __distance(RandomAccessIterator first, RandomAccessIterator last, Distance& n, random_access_iterator_tag) 
{
  	n += last - first;
}

__type_traits型别

Traits技术只是用来规范迭代器,对于迭代器之外的东西没有加以规范。因此,SGI将该技术扩展到迭代器之外,称为__type_traits。

萃取的型别如下(non-trivial意指非默认的相应函数):

  • 是否具备non-trivial default ctor?
  • 是否具备non-trivial copy ctor?
  • 是否具备non-trivial assignment operator?
  • 是否具备non-trivial dtor?
  • 是否为POD(plain old data)型别?

我们不能将参数设为bool值, 因为需要在编译期就决定该使用哪个函数, 所以需要利用函数模板的参数推导机制, 将__true_type和__false_type表现为一个空类, 就不会带来额外的负担, 又能表示真假, 还能在编译时类型推导就确定执行相应的函数。

struct __true_type {};
struct __false_type {};

实现:
将基础的类型都设置为__true_type型别。

__STL_TEMPLATE_NULL 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;
};

__STL_TEMPLATE_NULL struct __type_traits<signed 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;
};

...

将指针进行特化处理, 同样是__true_type型别。

#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION

template <class T>
struct __type_traits<T*>
{
   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;
};

#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */

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;
};

struct __type_traits<signed 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;
};

struct __type_traits<unsigned 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;
};

SGI将所有的内嵌型别都定义为false_type, 这是对所有的定义最保守的值。

template <class 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;
};

__true_type型别让我们在执行普通类型时能够以最大效率进行对其的copy, 析构等操作。如下面的uninitialized系列函数

uninitialized系列函数

在这里插入图片描述

uninitialized_copy

把 [first, last) 上的内容复制到以 result 为起始处的空间,返回复制结束的位置。

template <class InputIterator, class ForwardIterator>
inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result)
{
	// value_type取出类型
	return __uninitialized_copy(first, last, result, value_type(result));
}

// const char*特化版本
inline char* uninitialized_copy(const char* first, const char* last, char* result)
{
	memmove(result, first, last - first);
	return result + (last - first);
}

// const wchar_t*特化版本
inline wchar_t* uninitialized_copy(const wchar_t* first, const wchar_t* last, wchar_t* result)
{
	memmove(result, first, sizeof(wchar_t) * (last - first));
	return result + (last - first);
}

uninitialized_copy调用了__uninitialized_copy

template <class InputIterator, class ForwardIterator, class T>
inline ForwardIterator __uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result, T*)
{
	// POD指的是传统的c struct型别
	typedef typename __type_traits<T>::is_POD_type is_POD;
	return __uninitialized_copy_aux(first, last, result, is_POD());
}

// 是POD类型直接copy
template <class InputIterator, class ForwardIterator> 
inline ForwardIterator __uninitialized_copy_aux(InputIterator first, InputIterator last, ForwardIterator result, __true_type)
{
	return copy(first, last, result);
}

// 不是POD类型需要调用构造函数
template <class InputIterator, class ForwardIterator>
ForwardIterator __uninitialized_copy_aux(InputIterator first, InputIterator last, ForwardIterator result, __false_type)
{
	ForwardIterator cur = result;
	__STL_TRY
	{
		for ( ; first != last; ++first, ++cur)
			construct(&*cur, *first);
		return cur;
	}
	__STL_UNWIND(destroy(result, cur));
}
uninitialized_fill

从first到last范围内的都填充为 x 的值

template <class ForwardIterator, class T>
inline void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x) 
{
	// value_type取出类型
	__uninitialized_fill(first, last, x, value_type(first));
}

template <class ForwardIterator, class T, class T1>
inline void __uninitialized_fill(ForwardIterator first, ForwardIterator last,  const T& x, T1*)
{
	typedef typename __type_traits<T1>::is_POD_type is_POD;
	__uninitialized_fill_aux(first, last, x, is_POD());
}

// 是POD类型直接填充
template <class ForwardIterator, class T>
inline void __uninitialized_fill_aux(ForwardIterator first, ForwardIterator last,  const T& x, __true_type)
{
	fill(first, last, x);
}

// 不是POD类型需要调用构造函数来填充
template <class ForwardIterator, class T>
void __uninitialized_fill_aux(ForwardIterator first, ForwardIterator last, const T& x, __false_type)
{
	ForwardIterator cur = first;
	__STL_TRY
	{
		for ( ; cur != last; ++cur)
			construct(&*cur, x);
	}
	__STL_UNWIND(destroy(first, cur));
}
uninitialized_fill_n

从first开始n 个元素填充成 x 值

template <class ForwardIterator, class Size, class T>
inline ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x) 
{
	// value_type取出类型
	return __uninitialized_fill_n(first, n, x, value_type(first));
}

template <class ForwardIterator, class Size, class T, class T1>
inline ForwardIterator __uninitialized_fill_n(ForwardIterator first, Size n, const T& x, T1*) 
{
	typedef typename __type_traits<T1>::is_POD_type is_POD;
	return __uninitialized_fill_n_aux(first, n, x, is_POD());                                
}

// 是POD类型直接填充
template <class ForwardIterator, class Size, class T>
inline ForwardIterator __uninitialized_fill_n_aux(ForwardIterator first, Size n, const T& x, __true_type) 
{
	return fill_n(first, n, x);
}

// 不是POD类型需要调用构造函数来填充
template <class ForwardIterator, class Size, class T>
ForwardIterator __uninitialized_fill_n_aux(ForwardIterator first, Size n, const T& x, __false_type) 
{
  	ForwardIterator cur = first;
  	__STL_TRY 
  	{
   		for ( ; n > 0; --n, ++cur)
     	 	construct(&*cur, x);
    	return cur;
  	}
  	__STL_UNWIND(destroy(first, cur));
}

MyTinySTL迭代器

涉及到的文件iterator.h、type_traits.h、uninitialized.h,虽然uninitialized应该算是算法里面的,但是可以先用来初探迭代器的使用。

type_traits

m_integral_constant为一个静态常量,这边使用为bool常量。

template <class T, T v>
struct m_integral_constant
{
	static constexpr T value = v;	/*! 静态常数值 */
};

m_bool_constant 为一个bool常量,m_true_typem_false_type就是编译期间的true和false了。

template <bool b>
using m_bool_constant = m_integral_constant<bool, b>;

/*! true */
typedef m_bool_constant<true>  m_true_type;

/*! false */
typedef m_bool_constant<false> m_false_type;

这文件里面还有一个判断是否为pair的:

/* pair的前置声明 */
template <class T1, class T2>
struct pair;

template <class T>
struct is_pair : public mystl::m_false_type {};

template <class T1, class T2>
struct is_pair<mystl::pair<T1, T2>> : public mystl::m_true_type {};

迭代器萃取

迭代器类型和迭代器的模板都和上面介绍过的一模一样,我就不贴代码了。

萃取迭代器所有相关信息

有针对指针的偏特化版本,指针当成随机访问迭代器。

template <class Iterator>
struct iterator_traits : public iterator_traits_helper<Iterator, has_iterator_cat<Iterator>::value> {};

/*! 针对原生指针的偏特化版本 */
template <class T>
struct iterator_traits<T*>
{
	typedef random_access_iterator_tag           iterator_category;
	typedef T                                    value_type;
	typedef T*                                   pointer;
	typedef T&                                   reference;
	typedef ptrdiff_t                            difference_type;
};

/*! 针对原生const指针的偏特化版本 */
template <class T>
struct iterator_traits<const T*>
{
	typedef random_access_iterator_tag           iterator_category;
	typedef T                                    value_type;
	typedef const T*                             pointer;
	typedef const T&                             reference;
	typedef ptrdiff_t                            difference_type;
};

其中has_iterator_cat判断是否有迭代器类别iterator_category,这里定义了struct two大小是2用来区别char类型大小为1。然后有两个重载的模板参数test,通过传入的模板类型有无typename U::iterator_category来返回two 还是char,最后value通过反映出来。
也就是value = sizeof(test<T>(0)) == sizeof(char)test<T>(0)会去匹配test函数,如果有T中有定义iterator_category类型就返回twovalue就是true,否则返回charvalue就是false

template <class T>
struct has_iterator_cat
{
private:
	struct two { char a; char b; };
	template <class U> static two test(...);
	template <class U> static char test(typename U::iterator_category* = 0);
public:
	static const bool value = sizeof(test<T>(0)) == sizeof(char);
};

has_iterator_cat返回值传给iterator_traits_helper第二个参数 ,如果为false就没必要继续萃取了,如果为true则继承iterator_traits_impl
template <class From, class To> struct is_convertible;用来判断From是否可隐式转换为To
所以这边就是判断Iterator::iterator_category算否可以隐式转换为输入迭代器或输入迭代器。

/*! 没有迭代器类型 */
template <class Iterator, bool>
struct iterator_traits_helper {};

/*! 有迭代器类型 判断是否能隐式转换为input_iterator_tag或output_iterator_tag */
template <class Iterator>
struct iterator_traits_helper<Iterator, true> : public iterator_traits_impl<Iterator,
	std::is_convertible<typename Iterator::iterator_category, input_iterator_tag>::value ||
	std::is_convertible<typename Iterator::iterator_category, output_iterator_tag>::value> {};

如果不能隐式转换也就没必要萃取了,如果能转换就得到所有迭代器信息。

/*! 不能隐式转换为input_iterator_tag 或 output_iterator_tag */
template <class Iterator, bool>
struct iterator_traits_impl {};

/*! 能隐式转换为input_iterator_tag 或 output_iterator_tag 定义相关类型 */
template <class Iterator>
struct iterator_traits_impl<Iterator, true>
{
	typedef typename Iterator::iterator_category iterator_category;
	typedef typename Iterator::value_type        value_type;
	typedef typename Iterator::pointer           pointer;
	typedef typename Iterator::reference         reference;
	typedef typename Iterator::difference_type   difference_type;
};

辅助萃取

使用了上边说的iterator_traits

/*! 萃取迭代器的类型 */
template <class Iterator>
typename iterator_traits<Iterator>::iterator_category iterator_category(const Iterator&)
{
	typedef typename iterator_traits<Iterator>::iterator_category Category;
	return Category();
}

/*! 萃取迭代器之间距离的类型 */
template <class Iterator>
typename iterator_traits<Iterator>::difference_type* distance_type(const Iterator&)
{
	return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);
}

/*! 萃取迭代器指向值的类型 */
template <class Iterator>
typename iterator_traits<Iterator>::value_type* value_type(const Iterator&)
{
	return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
}

判断迭代器具体类型

这边也是判断是否能隐式转换

/*! T类型迭代器能隐式转换为U类型迭代器 */
template <class T, class U, bool = has_iterator_cat<iterator_traits<T>>::value>
struct has_iterator_cat_of : public m_bool_constant<std::is_convertible<
	typename iterator_traits<T>::iterator_category, U>::value> {};

/*! T类型迭代器无法隐式转换为U类型迭代器 */
template <class T, class U>
struct has_iterator_cat_of<T, U, false> : public m_false_type {};

/*! 判断是否为input_iterator_tag类别迭代器 */
template <class Iter>
struct is_input_iterator : public has_iterator_cat_of<Iter, input_iterator_tag> {};

/*! 判断是否为output_iterator_tag类别迭代器 */
template <class Iter>
struct is_output_iterator : public has_iterator_cat_of<Iter, output_iterator_tag> {};

/*! 判断是否为forward_iterator_tag类别迭代器 */
template <class Iter>
struct is_forward_iterator : public has_iterator_cat_of<Iter, forward_iterator_tag> {};

/*! 判断是否为bidirectional_iterator_tag类别迭代器 */
template <class Iter>
struct is_bidirectional_iterator : public has_iterator_cat_of<Iter, bidirectional_iterator_tag> {};

/*! 判断是否为random_access_iterator_tag类别迭代器 */
template <class Iter>
struct is_random_access_iterator : public has_iterator_cat_of<Iter, random_access_iterator_tag> {};

/*! 判断是否为迭代器 所有迭代器都是从input_iterator_tag 和 output_iterator_tag派生来的 */
template <class Iterator>
struct is_iterator : public m_bool_constant<is_input_iterator<Iterator>::value || is_output_iterator<Iterator>::value> {};

通过迭代器类型的应用:计算距离、移动迭代器

计算first迭代器和last迭代器之间的距离,如果是随机访问迭代器就可以像处理指针一样计算距离,否则就需要慢慢遍历,效率差别很大。

template <class InputIterator>
typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last)
{
	// 按照迭代器种类分类处理
	return distance_dispatch(first, last, iterator_category(first));
}

/*! 计算first迭代器和last迭代器之间的距离 input_iterator_tag版本 按照链表的方式计算 */
template <class InputIterator>
typename iterator_traits<InputIterator>::difference_type distance_dispatch(InputIterator first, InputIterator last, input_iterator_tag)
{
	typename iterator_traits<InputIterator>::difference_type n = 0;
	while (first != last)
	{
		++first;
		++n;
	}
	return n;
}

/*! 计算first迭代器和last迭代器之间的距离 random_access_iterator_tag版本 按照指针的方式计算 */
template <class RandomIter>
typename iterator_traits<RandomIter>::difference_type distance_dispatch(RandomIter first, RandomIter last, random_access_iterator_tag)
{
	return last - first;
}

让迭代器i前进n个距离,如果是随机访问迭代器就可以像处理指针一样移动,否则只能遍历,并且如果是双向迭代器才可以往后遍历,否则只能往前。

template <class InputIterator, class Distance>
void advance(InputIterator& i, Distance n)
{
	// 按照迭代器种类分类处理
	advance_dispatch(i, n, iterator_category(i));
}

/*! 让迭代器i前进n个距离 random_access_iterator_tag版本 可以后退 */
template <class RandomIter, class Distance>
void advance_dispatch(RandomIter& i, Distance n, random_access_iterator_tag)
{
	i += n;
}

/*! 让迭代器i前进n个距离 bidirectional_iterator_tag版本 可以后退 */
template <class BidirectionalIterator, class Distance>
void advance_dispatch(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag)
{
	if (n >= 0)
	{
		while (n--)
		{
			++i;
		}
	}
	else
	{
		while (n++)
		{
			--i;
		}
	}
}

/*! 让迭代器i前进n个距离 input_iterator_tag版本 不能后退 */
template <class InputIterator, class Distance>
void advance_dispatch(InputIterator& i, Distance n, input_iterator_tag)
{
	while (n--)
	{
		++i;
	}
}

反向迭代器

代码就不全贴了,从下面代码就能看出反向迭代器中维护了一个正向迭代器,所有的操作都是正向迭代器的一个适配。

template <class Iterator>
class reverse_iterator
{
private:
	Iterator current;  /*! 记录对应的正向迭代器 */

public:
	typedef typename iterator_traits<Iterator>::iterator_category iterator_category;	/*! 迭代器类别 */
	typedef typename iterator_traits<Iterator>::value_type        value_type;			/*! 数据 类型 */
	typedef typename iterator_traits<Iterator>::difference_type   difference_type;		/*! 迭代器之间的距离 类型 */
	typedef typename iterator_traits<Iterator>::pointer           pointer;				/*! 数据指针 */
	typedef typename iterator_traits<Iterator>::reference         reference;			/*! 数据引用 */

	typedef Iterator                                              iterator_type;	/*! 正向迭代器类别 */
	typedef reverse_iterator<Iterator>                            self;				/*! 反向迭代器类别 */
	。。。
	/*! 运算符重载* 实际对应正向迭代器的前一个位置 */
	reference operator*() const
	{
		auto tmp = current;
		return *--tmp;
	}
	/*! 运算符重载++ */
	self operator++(int)
	{
		self tmp = *this;
		--current;
		return tmp;
	}
	。。。
}

初始化空间(大块内存)构造元素

把 [first, last) 上的内容复制到以 result 为起始处的空间,返回复制结束的位置。
通过迭代器所指对象类型,使用is_trivially_copy_assignable判断出是否有系统定义的构造函数,如果有就没必要调用构造函数了直接copy,否则只能一个一个构造对象。

template <class InputIter, class ForwardIter>
ForwardIter uninitialized_copy(InputIter first, InputIter last, ForwardIter result)
{
	return mystl::unchecked_uninit_copy(first, last, result,
		std::is_trivially_copy_assignable<
		typename iterator_traits<ForwardIter>::
		value_type>{});
}

/*! 元素类型有普通复制构造函数 */
template <class InputIter, class ForwardIter>
ForwardIter unchecked_uninit_copy(InputIter first, InputIter last, ForwardIter result, std::true_type)
{
	return mystl::copy(first, last, result);
}

/*! 元素类型没有普通复制构造函数 */
template <class InputIter, class ForwardIter>
ForwardIter unchecked_uninit_copy(InputIter first, InputIter last, ForwardIter result, std::false_type)
{
	auto cur = result;
	try
	{
		for (; first != last; ++first, ++cur)
		{
			mystl::construct(&*cur, *first);
		}
	}
	catch (...)
	{
		for (; result != cur; ++result)
		{
			mystl::destroy(&*result);
		}
	}
	return cur;
}

其他的几个函数uninitialized_copy_nuninitialized_filluninitialized_fill_nuninitialized_moveuninitialized_move_n实现都类似的,我就不贴代码了。

  • 17
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值