侯捷 C++ STL标准库和泛型编程 —— 9 STL周围

news2024/12/23 11:39:30

最后一篇,完结辽!😋

9 STL周围

9.1 万用Hash Function

Hash Function的常规写法:其中 hash_val 就是万用Hash Function

class CustumerHash
{ 
public:
	size_t operator()(const Customer& c) const
	{ return hash_val(c.fname(), c.lname(), c.no()); }
};

还可以直接用函数实现,或者写一个 hash 的特化版本

原理:

通过三个函数重载实现从给入数据中逐一提取来不断改变 seed

// 第一个函数 首先进入该函数
template <typename... Types>
inline size_t hash_val(const Type&... args)
{
	size_t seed = 0; // 设置初始seed
	hash_val(seed, args...); // 进入第二个函数
	return seed; // seed就是最后的HashCode
}

// 第二个函数 该函数中逐一提取一个参数
template <typename T, typename... Types>
inline void hash_val(size_t& seed, const T& val, const Types&... args)
{
	hash_combine(seed, val); // 逐一取val,改变seed
	hash_val(seed, args...); // 递归调用自己,直到取完进入第三个函数
}

// 第三个函数
template <typename T>
inline void hash_val(size_t& seed, const T& val)
{
	hash_combine(seed, val); // 取最后一个val,改变seed
}

// 改变seed的函数
template <typename T>
inline void hash_combine(size_t& seed, const T& val)
{
    // 乱七八糟的运算,越乱越好
	seed ^= hash<T>()(val) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

C++11中 variadic templates

从传入的内容(任意个数,任意元素类型)分为一个和其他,递归再分为一个和其他······

0x9e3779b9:是黄金比例!

9.2 Tuple

可以将一些东西组合在一起

9.2.1 用例
  • 创建 tuple

    tuple<string, int, int, complex<double>> t; 
    
    tuple<int, float, string> t1(41, 6.3, "nico"); 
    
    auto t2 = make_tuple(22, 44, "stacy");
    
  • 输出 tuple

    // 输出t1中的第一个
    cout << get<0>(t1) << endl; // 41
    cout << t << endl; // 在VS2022上并没有<<的重载
    
  • 运算

    t1 = t2;
    
    if(t1 < t2) // 以特定的方式进行的比较
    {
        ...
    }
    
  • 绑定解包

    tuple<int, float, string> t3(77, 1.1, "more light");
    int i;
    float f;
    string s;
    
    tie(i, f, s) = t3; // i == 77, f == 1.1, s == "more light"
    
  • // tuple里有多少类型
    tuple_size< tuple<int, float, string> >::value; // 3
    
    // 取tuple里面的类型,前面一堆代表float
    tuple_element<1, TupleType>::type fl = 1.0; // float fl = 1.0;
    
9.2.2 原理

依然是使用 variadic templates,通过递归继承,不断从 ... 中提取内容

// 空的tuple
template <> class tuple<> {}; // 直到取完

// tuple主体
template <typename Head, typename... Tail>
class tuple<Head, Tail...>
	: private tuple<Tail...> // 递归继承
{
    typedef tuple<Tail...> inherited;
public:
	tuple() {}
	tuple(Head v, Tail... vtail) 
        : m_head(v), inherited(vtail...) {}
	...
protected:
	Head m_head; // 每次取出的元素
};

image-20230923111219018 👈🏻不断的继承就可以实现不同类型的组合了

其余函数:

...
{
public:
    ...
	Head head() { return m_head; }
	inherited& tail() { return *this; } // 通过转型获得Tail部分
    ...
};

image-20230923112317405 一般不这么用

9.3 type traits

9.3.1 用例

GCC2.9中:

默认的 __type_traits 进行了一系列泛化的设定(trivial 是不重要的意思)

 struct __true_type {};
struct __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; // Plain Old Data 类似C的struct
};

还会通过特化来实现针对不同类型的设定,例

template <> struct __type_traits<int>
{
	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;
};

C++11中:
有了很多个 type traits,可以回答更多问题

测试:

cout << is_void<T>::value << endl;
cout << is_integral<T>::value << endl;
cout << is_floating_point<T>::value << endl;
cout << is_array<T>::value << endl;
...
image-20230923192837871

不论是什么类型都可以自动检测它的 traits,非常厉害!(里面有虚函数——就能自动检测出它有多态性)

9.3.2 原理

模板的作用

is_integral

依然是采用的一种问答的方式实现的

template <typename _Tp>
struct is_integral
	:public __is_intagral_helper<typename remove_cv<_Tp>::type>::type
{ };

首先 remove_cvconstvolatile

// 通过偏特化实现remove const
template <typename _Tp>
struct remove_const
{ typedef _Tp type };

template <typename _Tp>
struct remove_const<_Tp const>
{ typedef _Tp type };

// remove volatile 同理

再通过 __is_intagral_helper 进行问答

// 通过偏特化实现
template <typename>
struct __is_integral_helper
	:public false_type { };

template <>
struct __is_integral_helper<bool>
	:public true_type { };

template <>
struct __is_integral_helper<int>
	:public true_type { };

template <>
struct __is_integral_helper<long>
	:public true_type { };

...

其他深入 class 内部的一些 traits 比如是否有虚函数,是否是一个类,是否是POD等等,其实现可能都与编译器有关

9.4 move

moveable class 中有:

// move ctor
MyString(MyString&& str) noexcept // 用&&与普通版本区别开
    : _data(str._data), _len(str._len)
{
    str._len = 0;
    str._data = NULL; // 避免析构函数释放资源
}

// move assignment
MyString& operator=(MyString&& str) noexcept
{
    if (this != &str)
    {
        _len = str._len;
        _data = str._data;
        str._len = 0;
        str._data = NULL; // 避免析构函数释放资源
    }
    return *this;
}

// dtor
virtual ~MyString()
{
    if(_data) delete _data; // 一定要检查
}
MyString C11(C1); // ctor
MyString C12(move(C1)); // move ctor

image-20230924094317369 是==浅拷贝==,并且把之前的指向去除了

对于 vector 这样的容器,其用 move 就只是 swap 了三根指针,非常快!

move 之后原来的东西不能再使用,比如拿数据插入容器,用临时对象,编译器看到就会自动使用 move 版本的

MyString C11(C1); 时,创建了一个实例 C11,编译器就不知道是否能用 move,就需要自己 MyString C12(move(C1)); 使用 move,但注意之后==一定不能用原来的 C1==

&&(右值引用)这是C++11引入的特性,右值引用用于处理临时对象或将资源所有权转移给其他对象,以提高性能和资源管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1061088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

x64内核实验2-段机制的变化

x64内核实验2-段机制的变化 ia-32e模式简介 x86下的段描述符结构图如下 在x86环境下段描述符主要分为3个部分的内容&#xff1a;base、limit、attribute&#xff0c;而到了64位环境下段的限制越来越少&#xff0c;主要体现在base和limit已经不再使用而是直接置空&#xff0…

U盘里文件损坏无法打开怎么恢复?

U盘&#xff0c;全称为USB闪存盘&#xff0c;是一种体积小巧、传输数据速度快的便携式存储设备。由于其出色的便捷性和高效性&#xff0c;U盘在各个工作领域和日常生活中得到了广泛应用&#xff0c;赢得了消费者的普遍好评。然而&#xff0c;使用U盘的过程中也可能会面临数据损…

Zabbix配置监控文件系统可用空间小于30GB自动告警

一、创建监控项 二、配置监控项 #输入名称–>键值点击选择 #找到磁盘容量点击 注&#xff1a; 1、vfs 该键值用于检测磁盘剩余空间&#xff0c;zabbix 内置了非常多的键值可以选着使用 2、单位B不需要修改&#xff0c;后期图表中单位和G拼接起来就是GB 3、更新时间 10S…

Qt扫盲-QSqlTableModel理论总结

QSqlTableModel理论总结 一、概述二、使用1. 与 view 视图绑定2. 做中间层&#xff0c;不显示 三、常用函数 一、概述 QSqlTableModel是用于从单个表读写数据库记录的高级接口。它构建在较低级的QSqlQuery之上&#xff0c;可用于向QTableView 等视图类提供数据。这个主要是对单…

基于三平面映射的地形纹理化【Triplanar Mapping】

你可能遇到过这样的地形&#xff1a;悬崖陡峭的一侧的纹理拉伸得如此之大&#xff0c;以至于看起来不切实际。 也许你有一个程序化生成的世界&#xff0c;你无法对其进行 UV 展开和纹理处理。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 三平面映射&#xff08;Trip…

【C++】String -- 详解

⚪C语言中的字符串 C 语言中&#xff0c;字符串是以 \0 结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C 标准库中提供了一些 str 系列的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合 OOP 的思想&#xff0c;而且底层空间需要用户自己…

Java实现整数互转罗马数字基本算法

目录 一、罗马数字的起源&#xff1f; 二、算法代码 &#xff08;1&#xff09;整数转罗马数字算法代码 &#xff08;2&#xff09;罗马数字转整数算法代码 三、测试结果 &#xff08;1&#xff09;整数转罗马数字测试结果 &#xff08;2&#xff09;罗马数字转整数测试…

GD32F103 硬件 IIC

1. 硬件IIC 1. 硬件IIC的框图 如果MCU做为主机SCL就做为输出&#xff0c;做从机SCL就做为输入。 主机&#xff1a; 当MCU作为主机发送数据流程从数据缓冲寄存器里拿到移位寄存器。在从移位寄存器一位一位发送。 当MCU作为主机接收数据流程先放到移位寄存器。在从移位寄存…

微信小程序软件著作权申请成功!

软件著作权登记是对自己开发的软件享有著作权的一种保障&#xff0c;也是对自己开发能力的一种认证&#xff0c;在个人找工作或者公司拿项目资质审查时都可能发挥作用。我成功开发了一款微信小程序后&#xff0c;便了解了许多相关资料&#xff0c;花钱请代理代办速度快、省事&a…

Visopsys 0.92 发布

Visopsys 是一个 PC 机的操作系统&#xff0c;系统小型、快速而且开源。有着丰富的图形界面、抢先式多任务机制以及支持虚拟内存。Visopsys 视图兼容很多操作系统&#xff0c;但并不是他们的克隆版本。Visopsys 0.92 现已发布&#xff0c;此维护版本引入了多任务处理程序、文件…

C++标准模板(STL)- 类型支持 (定宽整数类型)(int8_t,int_fast8_t,int_least8_t,intmax_t,intptr_t)

定宽整数类型 类型 定义于头文件 <cstdint> int8_tint16_tint32_tint64_t (可选) 分别为宽度恰为 8、16、32 和 64 位的有符号整数类型 无填充位并对负值使用补码 &#xff08;仅若实现支持该类型才提供&#xff09; (typedef) int_fast8_tint_fast16_tint_fast32_tint…

进程调度算法之先来先服务(FCFS),短作业优先(SJF)以及高响应比优先(HRRN)

1.先来先服务&#xff08;FCFS&#xff09; first come first service 1.算法思想 主要从“公平”的角度考虑(类似于我们生活中排队买东西的例子) 2.算法规则 按照作业/进程到达的先后顺序进行服务。 3.用于作业/进程调度 用于作业调度时&#xff0c;考虑的是哪个作业先…

Spring 原理

它是一个全面的、企业应用开发一站式的解决方案&#xff0c;贯穿表现层、业务层、持久层。但是 Spring仍然可以和其他的框架无缝整合。 1 Spring 特点 轻量级控制反转面向切面容器框架集合 2 Spring 核心组件 3 Spring 常用模块 4 Spring 主要包 5 Spring 常用注解 bean…

【HTTP】URL结构、HTTP请求和响应的报文格式、HTTP请求的方法、常见的状态码、GET和POST有什么区别、Cookie、Session等重点知识汇总

目录 URL格式 HTTP请求和响应报文的字段&#xff1f; HTTP请求方法 常见的状态码 GET 和 POST 的区别 Cookie 和 Session URL格式 &#xff1f;&#xff1a;是用来分割URL的主体部分&#xff08;通常是路径&#xff09;和查询字符串&#xff08;query string&#xff09;…

MyBatisPlus(九)模糊查询

说明 模糊查询&#xff0c;对应SQL语句中的 like 语句&#xff0c;模糊匹配“要查询的内容”。 like /*** 查询用户列表&#xff0c; 查询条件&#xff1a;姓名包含 "J"*/Testvoid like() {String name "J";LambdaQueryWrapper<User> wrapper ne…

十天学完基础数据结构-第六天(树(Tree))

树的基本概念 树是一种层次性的数据结构&#xff0c;它由节点组成&#xff0c;这些节点按照层次关系相互连接。树具有以下基本概念&#xff1a; 根节点&#xff1a;树的顶部节点&#xff0c;没有父节点。 子节点&#xff1a;树中每个节点可以有零个或多个子节点。 叶节点&am…

力扣第102题 广度优先搜索 二叉数 c++

题目 102. 二叉树的层序遍历 中等 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20…

八大排序算法汇总(C语言实现)

本专栏内容为&#xff1a;八大排序汇总 通过本专栏的深入学习&#xff0c;你可以了解并掌握八大排序以及相关的排序算法。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;八大排序汇总 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库…

【1++的刷题系列】之双指针

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的刷题系列】 文章目录 一&#xff0c;什么是双指针二&#xff0c;相关例题例一例二例三例四例五 一&#xff0c;什么是双指针 常见的双指针有两种形式&#xff1a;一种是对撞指针&#xff08…

tinymce富文本编辑器【tip】

项目场景&#xff1a; tinymce富文本编辑器在iview的modal框中显示的问题 问题描述 最近在使用tinymceiviewvue写项目&#xff0c;在富文本编辑器配合弹框一起使用时&#xff0c;总是存在问题&#xff1a;弹框弹出的时候&#xff0c;富文本编辑器不能点击&#xff0c;鼠标的光…