@著作权归作者所有:来自CSDN博客作者大胡子的艾娃的原创作品,如需转载,请注明出处https://blog.csdn.net/qq_43148810,否则将追究法律责任。 如有错误的地方欢迎指正,谢谢!
一、从模板函数std::distance(计算迭代器的距离)开始
#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <stack>
#include <set>
#include <map>
int main(int argc, char*argv[])
{
std::vector<int> vec;
for (int i = 0; i < 10; ++i)
{
vec.push_back(i);
}
auto d = vec.end() - vec.begin();
auto itrDis = std::distance(vec.begin(), vec.end());
return 0;
}
1、stack、queue、priority_queue容器无迭代器,即不能使用此函数。 2、vector、deque容器重载了operator-,实现了计算std::distance功能。内存连续型(迭代器可跳跃)容器,距离为迭代器直接相减。
_NODISCARD difference_type operator-(const _Mybase& _Right) const
{
return (*(_Mybase *)this - _Right);
}
3、list、set、map容器没有实现operator-,内存不连续型(迭代器不可跳跃)容器。
二、distance模板函数实现剖析
template<class _InIt>
_CONSTEXPR17 _Iter_diff_t<_InIt> _Distance1(_InIt _First, _InIt _Last, input_iterator_tag)
{
_Iter_diff_t<_InIt> _Off = 0;
for (; _First != _Last; ++_First)
{
++_Off;
}
return (_Off);
}
template<class _RanIt>
_CONSTEXPR17 _Iter_diff_t<_RanIt> _Distance1(_RanIt _First, _RanIt _Last, random_access_iterator_tag)
{
return (_Last - _First);
}
template<class _Iter>
using _Iter_cat_t = typename iterator_traits<_Iter>::iterator_category;
template<class _InIt>
_NODISCARD _CONSTEXPR17 _Iter_diff_t<_InIt> distance(_InIt _First, _InIt _Last)
{
return (_Distance1(_First, _Last, _Iter_cat_t<_InIt>()));
}
1、由_Distance1函数实现,并且_Distance1有两个重载版本(VS2017),其他编译器可能有多个,但并无分别。 2、由第三参数类型input_iterator_tag和random_access_iterator_tag用来重载,也仅仅是用来重载,并未使用类型对象。 3、_Iter_cat_t<_InIt>()则用来萃取(向迭代器提问)其类型,而iterator_category即是答案。
typename T::iterator_category cagy2;
4、迭代器除了可以回答与之容器对应的迭代器类型,还可以回答一下类型。
typedef bidirectional_iterator_tag iterator_category
typedef ptrdiff_t difference_type
typedef size_t size_type
typedef T value_type
typedef T* pointer
typedef &T reference
例如:
typename std::iterator_traits<T>::difference_type diff_type;
5、迭代器的五种类型,按移动性质分类,不是枚举、常量宏等类型,为struct,属性在此等同class,并且有继承关系。
struct input_iterator_tag
{
};
struct output_iterator_tag
{
};
struct forward_iterator_tag
: input_iterator_tag
{
};
struct bidirectional_iterator_tag
: forward_iterator_tag
{
};
struct random_access_iterator_tag
: bidirectional_iterator_tag
{
};
6、_Distance1模板函数只实现的两个重载版本(内存是否连续型或者说迭代器是否可跳跃),因为继承关系其他类型向上兼容。VS2017只有该两个版本,其他版本编译器可能有多个版本。
到此完完全全讲清楚了模板函数std::distance怎么实现计算迭代器之间的距离。 如对容器的数据结构,底层实现不清楚的可参考: C++STL容器总结:https://blog.csdn.net/qq_43148810/article/details/118229552
三、类型萃取,惊鸿一瞥 ,STL六大组件关系
总结:Container通过Allocator取得数据的储存空间,Algorithm通过Iterator存取Container内容,Functor可以协助Algorithm完全不同的策略变化,Adapter可以修饰或者套接Functor。
1、std::distance(计算迭代器的距离)算法很好的解释了以上“总结”斜线部分。 2、STL称之为标准模板库,C++面对对对象语言,标准库多为模板编程、元编程的手法,而非面对对象的手法。换而言之多为静态多态性,而非虚函数代表的动态多态性。 3、traits(萃取机)并非六大组件,但是在STL中起到至关重要的作用。 4、由此打开元编程(对类型操作,而非对象)的大门
更多内容请关注个人博客:https://blog.csdn.net/qq_43148810
|