STL源码笔记之型别提取技法(2)

2024-05-04 23:32

本文主要是介绍STL源码笔记之型别提取技法(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.iterator_category

    (1)Input Iterator:这种迭代器所指的对象,不允许外接改变,只读。    

    (2)Output Iterator:只写。

    (3)Forward Iterator:允许“写入型”算法在此迭代器所形成的区间上进行读写操作。

    (4)Bidirectional Iterator:可双向移动。某些算法需要逆向走访某个迭代器区间,可使用Bidirectional Iterator。

    (5)Random Access Iterator:前四种迭代器只提供一部分指针的能力(前三种只支持operator++,operator--),第五种涵盖所有指针算术能力。包括p+n、p-n、p[n]、p1-p2,p1<p2。

      为了能够提供编译迭代器动态选择,STL定义了五种标记用的型别,这样我们在调用涉及到迭代器的函数时,就能选择符合相应迭代器特性的函数。五个迭代器分别为:

                  struct input_iterator_tag{};

                  struct output_iterator_tag{};

                  struct forward_iterator_tag: public input_iterator_tag{};

                  struct bidirection_iterator_tag: public forward_iterator_tag{};

                  struct random_access_iterator_tag: public bidirection_iterator_tag{};

这些class只作标记使用,不占用任何空间。

//advance()为例
//最后一个参数只是用来重载,不需要任何成员
template<class InputIterator,class Distance>
inline void__advance(InputIterator& i,Distance n,input_iterator_tag)
{while(n--)++i;}
template<class ForwardIterator,class Distance>
inline void__advance(ForwardIterator& i,Distance n,forward_iterator_tag)
{
__advance(i,n,input_iterator_tag);
}
template<class BidirectionalIterator,class Distance>
inline void__advance(BidirectionalIterator& i,Distance n,bidirectional_iterator_tag)
{
if(n>=0)while(n--)++i;
else while(n++)--i;
}
template<class RandomAccessIterator,class Distance>
inline void__advance(RandomAccessIterator& i,Distance n,random_access_iterator_tag)
{
i+=n;
}
//调用的时候,InputIterator可以是所有上面的五种迭代器之一
template<class InputIterator,class Distance>
inline void advance(InputIterator& i,Distance n)
{
//自动选择上面的四个函数
//萃取iterator_category必须在每个iterator_traits里面
__advance( i,n,iterator_traits<InputIterator>::iterator_category());
}


2.std::iterator的保证

      为了符合规范,任何迭代器都必须要相应的型别,以利于traits萃取,否则便是自别于整个STL架构,可能无法与STL组件顺利搭配。STL定义了一个标准的iterator class,每个迭代器都继承自它,这样就保证了统一行。

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  Distance     difference_type;
typedef  Pointer        pointer;
typedef  Reference   reference  ;
};

      iterator class不含任何成员,纯粹型别定义,所以继承不会招致任何负担,由于后三个参数皆有默认值。故心得迭代器只需要提供两个参数即可。

template<class T>

struct ListIter:public std: iterator<std::forward_iterator_tag,Item>

{...........}

3.__type_traits

      类型粗略的讲有两种,一种是用class封转,并且它的复制拷贝很费时,比如需要深度复制,需要safe copying——即需要调用构造函数完成复制;另一种是所谓的POD(plain old data),一般是build-in类型或是c式的struct类型,这种类型复制和拷贝时只需直接复制内存块就可以了,于是有了bitwise copying或是trival construct/deconstruct/copy/assignment的概念。

      SGI STL中使用__type_traits就可以在编译期间就确定复制一个对象是调用赋值构造函数还是直接调用memcpy,从而提高效率。看SGI STL的源代码:

  1. struct __true_type {};  
  2. struct __false_type {};  
  3.   
  4. template <class type>   //primariy template  
  5. struct __type_traits {   
  6.      typedef __true_type     this_dummy_member_must_be_first;  
  7.       
  8.     typedef __false_type    has_trivial_default_constructor;  
  9.     typedef __false_type    has_trivial_copy_constructor;  
  10.     typedef __false_type    has_trivial_assignment_operator;  
  11.     typedef __false_type    has_trivial_destructor;  
  12.     typedef __false_type    is_POD_type;  
  13. };  
  14. __STL_TEMPLATE_NULL struct __type_traits<char> { //full specialization  
  15.     typedef __true_type    has_trivial_default_constructor;  
  16.     typedef __true_type    has_trivial_copy_constructor;  
  17.      typedef __true_type    has_trivial_assignment_operator;  
  18.     typedef __true_type    has_trivial_destructor;  
  19.     typedef __true_type    is_POD_type;  
  20. };  
  21. __STL_TEMPLATE_NULL struct __type_traits<int> {  
  22.     typedef __true_type    has_trivial_default_constructor;  
  23.     typedef __true_type    has_trivial_copy_constructor;  
  24.     typedef __true_type    has_trivial_assignment_operator;  
  25.     typedef __true_type    has_trivial_destructor;  
  26.     typedef __true_type    is_POD_type;  
  27. };  
接下来,看看怎样使用__type_trairt:
[cpp]  view plain copy
  1. template <class InputIterator, class ForwardIterator, class T>  
  2. inline ForwardIterator __uninitialized_copy(InputIterator first, InputIterator last,  
  3.                      ForwardIterator result, T*) {  
  4.         typedef typename __type_traits<T>::is_POD_type is_POD;  
  5.         return __uninitialized_copy_aux(first, last, result, is_POD());  
  6. }  
  7. template <class InputIterator, class ForwardIterator> inline ForwardIterator   
  8. __uninitialized_copy_aux(InputIterator first, InputIterator last,  
  9.                          ForwardIterator result, __true_type) {  
  10.         return copy(first, last, result); //STL 算法copy里面大有乾坤,针对POD类型,调用memmove,还含有iterator_trait的使用  
  11. }  
  12. template <class InputIterator, class ForwardIterator>  
  13. ForwardIterator __uninitialized_copy_aux(InputIterator first, InputIterator last,  
  14.                          ForwardIterator result, __false_type) {  
  15.         ForwardIterator cur = result;  
  16.         for ( ; first != last; ++first, ++cur)  
  17.                construct(&*cur, *first);  
  18.         return cur;  
  19.   }  
  20. }  

这篇关于STL源码笔记之型别提取技法(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/960331

相关文章

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个