《STL源码剖析》之type_traits

2023-10-27

阅读STL源码时有两个疑问:

        1.在源码中大量出现的typedef有什么用?

        2.源码中所谓的type_traits(类型萃取)是个什么东西?

其实这两个问题是有相关性的,想搞懂问题2必须先解决问题1

首先看STL中如何使用typedef,并解答问题1.

//STL中typedef大多用在相关容器的迭代器的设计中
//迭代器作为容器和算法之间沟通的桥梁,其作用就是在算法对某迭代器进行操作时
//告知算法有关当前容器的基本信息,如容器类型,容器中数据的类型等
//而typedef的作用就是将各容器中的基本信息统一命名,例如容器中数据元素的类型都叫value_type
//我们先来看STL中针对不同容器的迭代器的设计

//vector类
template <class T, class Alloc=alloc> //缺省使用alloc为vector的配置器
calss vector {
    public:
        typdef T value_type;
        typedef value_type* iterator;   //vector的迭代器是普通指针
        ...
};

//list的迭代器源码中这样设计
template <class T, class Ref, class Ptr>
struct _list_iterator {

    ....
    typedef T value_type;
    typedef Ref reference;
    typedef Ptr pointer;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;

}

//deque的迭代器设计
template <class T, class Ref, class Ptr>
struct _deque_iterator {

    ....
    typedef T value_type;
    typedef Ref reference;
    typedef Ptr pointer;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;//这五个是迭代器必须有的相应型别的内嵌类型定义

}

//如此这般,当算法sort拿到某种类型iterator迭代器进行排序操作时
//便可以通过统一的value_type名称获取当前操作的容器中的数据类型是什么
//我们接着看一下STL内置的sort算法如何使用typedef重命名的value_type
//sort部分源码
template <class RandomAccessIterator>
void _insertion_sort(RandomAccessIterator first, RandomAccessIterator last){
    if(first==last) return;
    for( RandomAccessIterator i = first+1, i!=last, ++i){
        _linear_insert (first, i, value_type(first));
    }

}
//可以看到 无论sort接收的是什么类型的iterator,统一使用value_type进行排序操作
//这就是typedef的作用,可以告诉算法当前迭代器所指向容器中元素的数据类型是什么

问题1解决了,那问题2就好解决了

先说type_traits(类型萃取)的作用:说人话,type_traits实际上就相当于一个中介,或者是背调公司,当算法需要获取当前接收到的迭代器所指向容器中的数据信息时,通过type_traits来调查这个iterator,并且返回iterator里面的五个必要信息给算法。

有了上面的typedef,算法已经可以通过迭代器获取当前容器中元素的信息了,为什么还要单独弄个type_traits呢?

答:可以看到上面的代码中,除了vector外,其他容器的迭代器都是struct结构,其中包含了当前容器内容的有关信息,而vector的迭代器只是一个普通指针,并不能包含其他信息。所以其他容器的迭代器是封装好的类似智能指针的东西,这些封装好的iterator内已经包含了算法需要的必要信息,但是vector容器的迭代器呢?你无法在原始指针里再去包含其他信息。这个时候中介公司traits的作用就体现出来了,中介公司可以再做一层封装,特殊情况我特殊处理一下,然后向算法提供统一的调用接口,这样就避免了算法还需要根据不同的容器类型去设计不同的处理方式,那traits是如何进行统一化处理的呢?看源码

//1.如果传给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;
};

//如果传给traits的迭代器是原始指针(如vector的迭代器),则这样获取
template <class _Tp>
struct iterator_traits<_Tp*> {
    typedef random_access_iterator_tag itrator_category;
    typedef _Tp                         value_type;
    typedef ptrdiff_t                    difference_type;
    typedef _Tp* pointer;
    typedef _Tp*& reference;
};


template <class _Tp>
struct iterator_traits<const _Tp*> {
    typedef random_access_iterator_tag itrator_category;
    typedef _Tp                         value_type;
    typedef ptrdiff_t                    difference_type;
    typedef _Tp* pointer;
    typedef _Tp*& reference;
};

可以看到,traits对不同种类的迭代器分别进行处理,当算法向traits询问当前迭代器所指容器中的各种信息时,traits根据接收到的迭代器类型不同,使用不同的访问方式,将获得的信息返回给算法,这样算法就方便了很多;

总结:迭代器Iterator作为算法对容器操作的桥梁,在面对不同种类型容器的迭代器时,为了避免算法麻烦,创建了traits这个中间人来统一向算法提供当前迭代器所指向容器中元素的相关信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《STL源码剖析》之type_traits 的相关文章

  • 如何使用MemoryCache代替Timer来触发一个方法?

    以下方法通过等待已运行操作的结果来处理并发请求 对数据的请求可能会使用相同 不同的凭据同时出现 对于每组唯一的凭据 最多可以有一个GetCurrentInternal呼叫正在进行中 当准备就绪时 该呼叫的结果将返回给所有排队的服务员 pri
  • C++ 中本地类中的静态成员变量?

    我知道我们不能宣布static本地类中的成员变量 但其原因尚不清楚 那么请问有人可以解释一下吗 另外 为什么我们不能访问非static函数内部定义的变量 内部已经定义了局部类 直接在局部类成员函数中 在下面给出的代码中 int main i
  • 如何检查QProcess是否正确执行?

    QProcess process sdcompare QString command sdcompare QStringList args sdcompare command sdcompare diff args sdcompare lt
  • 为 Visual Studio 2013 编译 Tesseract

    我正在尝试使用tesseract在 Visual Studio 2013 中 我在链接器 gt 输入 不是 libtesseract302 static lib 中使用 libtesseract302 lib 一切都正常 并且已编译并运行
  • 向 Nhibernate 发出 SQL 查询

    如何将此 SQL 查询发送给 Nhibernate SELECT Customer name FROM Company INNER JOIN Customer ON Company CompanyId Customer CompanyId
  • 如何将 #ifdef DEBUG 添加到 Xcode?

    我的项目中有一些代码永远不应该在发布版本中使用 但在测试时很有用 我想做这样的事情 ifdef DEBUG Run my debugging only code endif 在 Xcode 4 中哪里添加 DEBUG 设置 我尝试将其放入
  • 在新的浏览器进程中打开 URL

    我需要在新的浏览器进程中打开 URL 当浏览器进程退出时我需要收到通知 我当前使用的代码如下 Process browser new Process browser EnableRaisingEvents true browser Star
  • 在 Unity 进程和另一个 C# 进程之间进行本地 IPC 的最快方法 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我希望每秒大约 30 次从 C 应用程序向我的 Unity 应用程序传送大量数据 由于 Unity 不支持映射内存和管道 我考虑了 t
  • 单元测试一起运行时失败,单独运行时通过

    所以我的单元测试遇到了一些问题 我不能只是将它们复制并粘贴到这里 但我会尽力而为 问题似乎是 如果我一项一项地运行测试 一切都会按预期进行 但如果我告诉它一起运行测试 则 1 5 将通过 TestMethod public void Obj
  • 用于检查项目文件中的项目变量和引用路径的 api

    我正在研究一个 net application VS2010 与 x 没有 解和变量号这些解决方案中的项目数量 我需要检查项目属性 特定于一定数量的项目 是否同质 并且检查 验证构建期间的参考路径 有没有一个API是这样的吗 如果没有 我该
  • C# Dns.GetHostEntry 不返回连接到 WiFi 的移动设备的名称

    我有一个 C 中的 Windows 窗体应用程序 我试图获取列表中所有客户端的主机名 下面给出的是 ra00l 来自此链接的代码示例 GetHostEntry 非常慢 https stackoverflow com questions 99
  • 关于在 Windows 上使用 WiFi Direct Api?

    我目前正在开发一个应用程序 我需要在其中创建链接 阅读 无线网络连接 在桌面应用程序 在 Windows 10 上 和平板电脑 Android 但无关紧要 之间 工作流程 按钮 gt 如果需要提升权限 gt 创建类似托管网络的 WiFi 网
  • 将 Excel 导入到 Datagridview

    我使用此代码打开 Excel 文件并将其保存在 DataGridView 中 string name Items string constr Provider Microsoft Jet OLEDB 4 0 Data Source Dial
  • 如何编写一个同时需要请求和响应Dtos的ServiceStack插件

    我需要提供本地化数据服务 所有本地化的响应 Dto 都共享相同的属性 IE 我定义了一个接口 ILocalizedDto 来标记那些 Dto 在请求端 有一个ILocalizedRequest对于需要本地化的请求 Using IPlugin
  • std::async 与重载函数

    可能的重复 std bind 重载解析 https stackoverflow com questions 4159487 stdbind overload resolution 考虑以下 C 示例 class A public int f
  • (de)从 CSV 序列化为对象(或者最好是类型对象的列表)

    我是一名 C 程序员 试图学习 C 似乎有一些内置的对象序列化 但我在这里有点不知所措 我被要求将测试数据从 CSV 文件加载到对象集合中 CSV 比 xml 更受青睐 因为它更简单且更易于人类阅读 我们正在创建测试数据来运行单元测试 该集
  • Process.Start() 方法在什么情况下返回 false?

    From MSDN https msdn microsoft com en us library e8zac0ca v vs 110 aspx 返回值 true 表示有新的进程资源 开始了 如果由 FileName 成员指定的进程资源 St
  • 编译时“strlen()”有效吗?

    有时需要将字符串的长度与常量进行比较 例如 if line length gt 2 Do something 但我试图避免在代码中使用 魔法 常量 通常我使用这样的代码 if line length gt strlen Do somethi
  • 使用 GhostScript.NET 打印 PDF DPI 打印问题

    我在用GhostScript NET http ghostscriptnet codeplex com打印 PDF 当我以 96DPI 打印时 PDF 打印效果很好 但有点模糊 如果我尝试以 600DPI 打印文档 打印的页面会被极大地放大
  • 如何正确使用 std::condition_variable?

    我很困惑conditions variables以及如何 安全 使用它们 在我的应用程序中 我有一个创建 gui 线程的类 但是当 gui 是由 gui 线程构造时 主线程需要等待 情况与下面的函数相同 主线程创建互斥体 锁和conditi

随机推荐

  • Java 学生成绩管理系统 带详细设计报告 功能非常齐全 完整源码

    今天为大家分享一个java语言编写的学生成绩管理系统 目前系统功能已经很全面 后续会进一步完善 整个系统界面漂亮 有完整得源码 希望大家可以喜欢 喜欢的帮忙点赞和关注 一起编程 一起进步 开发环境 开发语言为Java 开发环境Eclipse
  • python实现选择排序

    排序算法 python实现基数排序 python实现归并排序 python实现交换排序 python实现选择排序 python实现插入排序 简单选择排序 基本思想 假设排序表为L 1 n 第i趟排序即从L i n 中选择关键字最小的的元素与
  • TensorFlow实现VGGNet网络模型

    1 VGGNet简介 VGGNet是牛津大学计算机视觉组和Google DeepMind公司的研究员一起研发的深度卷积神经网络 VGGNet探索了卷积神经网络的深度与其性能之间的关系 反复使用33的小型卷积核和22的最大池化层来构筑卷积神经
  • Pycharm创建项目时,解释器如何选择

    最近开始看深度学习 需要用到python 然后就安装了python Anaconda 还有编译IDE pycharm 给大家理一下关系 python就是一个解释器 用来解释程序用的 可以理解为普通C或者C语言的IDE环境 有gcc编译啊之类
  • 掌握Python的X篇_10+11_if分支语句、else语句、elif语句

    文章目录 1 if关键字及语法 2 语句块的概念 3 else语句 4 elif语句 1 if关键字及语法 基本语法如下 if 条件表达式 条件为True时 要执行的语句 举例 number int input Input an numbe
  • 给大家推荐几个查英语缩写的网站

    1 https www acronymfinder com 2 https www abbreviations com 转载于 https www cnblogs com cnwuchao p 10562539 html
  • 实验15:20211127 Java大数据1+X 中级实操考试(id:2660)

    实验15 20211127 Java大数据1 X 中级实操考试 id 2660 一 项目背景说明 二 表结构 三 步骤 5 分 步骤 1 项目准备 5 分 步骤 2 完成实体类 Student 10 分 步骤 3 完成实体类 Course
  • 构造函数不能被继承

    1 派生类不能继承基类的构造函数 必需提供自个的构造函数 防止紧耦合 继承一切成员 构造函数除外 2 析构函数同理 只是由于析构函数无参数需传递 所以似乎能合适的使用 逻辑上 提供 3 由系统隐式使用析构函数 缺省构造函数 class B
  • ubuntu Linux操作系统使用教程(学习笔记)

    本文为 Ubuntu Linux操作系统使用教程 人民邮电出版社 的个人学习笔记 第一章 系统介绍 Linux GNU GPL的关系 Linux的主要发行版本 Linux系统特性及与Windows的区别 略 第二章 系统部署 系统安装 略
  • 模板模式

    简介 在模板模式中 一个抽象类公开定义了执行它的方法的方式 模板 它的子类可以按需要重写方法实现 但调用将以抽象类中定义的方式进行 这种类型的设计模式属于行为型模式 主要解决 一些方法通用 却在每一个子类都重新写了这一方法 注意 一般模板方
  • Spring Bean (作用域,依赖注入四种方式,生命周期)

    附带Spring5 种不同方式的自动装配 一 Spring Bean 作用域 Spring 3 中为 Bean 定义了 5 中作用域 分别为 singleton 单例 prototype 原型 request session 和 globa
  • Mysql安装后登陆失败,(用户名/密码正确)

    使用 AppServ安装Mysql套件 安装完成后使用正确的用户名密码登陆MySQL 错误提示 提示用户名或密码不正确 解决方法 1 安装目录下找到my ini 2 修改my ini 在最后一行加入 skip grant tables 3
  • Postgresql杂谈 20—详解Postgresql中的Checkpoint、WAL日志和热备份恢复

    本文中 我们共同学习下Postgresql的WAL日志 WAL 是Write Ahead Log的简称 翻译过来就是预写日志 或者叫做重做日志 相信大家对数据库事务的四大特性ACID 原子性 一致性 隔离性和持久性 已经非常熟悉了 今天我们
  • VS编译报错集合

    error C2872 byte 不明确的符号 编译错误信息 error C2872 byte 不明确的符号 这里重复定义了byte类型 1 gt 可能是 k program files x86 microsoft sdks windows
  • OpenCV contrib编译及问题解决

    OpenCV是一个开源发行的跨平台计算机视觉和机器学习软件库 可以运行在Linux Windows Android和Mac OS操作系统上 OpenCV中包括很多类型的算法包 还有第三方及专利算法 在实际工程中 经常需要根据特性定制库 这就
  • 138. 复制带随机指针的链表

    LeetCode题解 前言 复制带随机指针的链表 前言 在刷题的过程中 遇到了一个很棒的思路 与是便记录了下来 复制带随机指针的链表 题目描述 挑战链接 分析 题目描述的很长 但是仔细阅读的话 我们会发现题目想表达的意思很明确 就是将题目给
  • 一个非常简洁好用的PHP实现EXCEL导出功能(精)

    直接复制粘贴到PHP脚本中就能导出EXCEL 自己根据需要替换 ReportArr里面的内容即可 输出的文件类型为excel header Content type application vnd ms excel 提示下载 header
  • 【OS实验】【学习笔记】

    文章目录 零 实验参考 实验1 熟悉实验环境 PS personal summary 实验2 操作系统的引导 PS personal summary 实验3 系统调用 Aim Do what PO Personal Oprate PS pe
  • Q_SIGNALS,Q_SLOTS, Q_EMIT

    http hi baidu com lhj dekongjian blog item 0bc212d12c2ac426960a1643 html CONFIG no keywords 它告诉QT不要定义moc关键字signals slots
  • 《STL源码剖析》之type_traits

    阅读STL源码时有两个疑问 1 在源码中大量出现的typedef有什么用 2 源码中所谓的type traits 类型萃取 是个什么东西 其实这两个问题是有相关性的 想搞懂问题2必须先解决问题1 首先看STL中如何使用typedef 并解答