STL分析(十 hash、function type_traits、cout、move )

news2024/12/26 12:01:49

hash function

假定存在一个Customer类

class Customer{
public:
    string fname, lname;
    int no;
};

其哈希函数存在三种方式

//方式一:创建可调用类型
class CustomerHash
{
public:
    std::size_t operator()(const Customer& c) const{
        return ......
    }
};
 
unordered_set<Customer, CustomerHash> custest;
 
 
//方式二:创建哈希函数
size_t customer_hash_func(const Customer& c){
    return ......
}
 
unordered_set<Customer, size_t(*)(const Customer&)> custest(20, customer_hash_func); //注意这里调用了构造函数的不同版本
 
 
//方式三:特化标准库提供的hash<T>
namespace std
{
template<>
struct hash<Customer>
{
    size_t
    operator()(const Customer& c) const noexcept
    { return ...... }
};
}
 
unordered_set<Customer> custest;

具体的hash function计算如下:标准库提供了一个hash_val的函数,可以计算出由基本类型组成的class的hash值,原理是使用了可变模板参数

template <typename... Types>
inline size_t hash_val(const Types&... args){        //提供给使用者的重载版本
    size_t seed = 0;
    hash_val(seed, args...);                         //实际调用的版本
    return seed;
}
 
template <typename T, typename... Types>
inline void hash_val(size_t& seed,                   //实际调用函数的主体
                     const T& val, const Types&... args){
    hash_combine(seed, val);
    hash_val(seed, args...);
}
 
template <typename T>
inline void hash_val(size_t& seed, const T& val){    //实际调用函数的边界条件
    hash_combine(seed, val);
}
 
template <typename T>
inline void hash_combine(size_t& seed, const T& val){
    seed ^= std::hash<T>()(val) + 0x9e3779b9
            + (seed<<6) + (seed>>2);
}![在这里插入图片描述](https://img-blog.csdnimg.cn/c7cdce1a463d409a9c81c2ffefb290f3.png)

 
 
 
//下面是对于 class Customer 的实际使用
class CustomerHash{
public:
    std::size_t operator()(const Customer& c) const{
        return hash_val(c.fname, c.lname, c.no);
    }
};
  • 此时可使用CustomerHash hh; hh(Customer("Ace", "Hou", 1L)) % 11来计算该对象应存放的hash bucket position。
  • 在使用该hash function创建unordered_set时可用unordered_set<Customer, CustomerHash> set3;方式调用。

tuple

在这里插入图片描述

注意:string的实现在各库中可能有所不同,但是在同一库中相同一点是,无论你的string里放多长的字符串,它的sizeof()都是固定的,字符串所占的空间是从堆中动态分配的,与sizeof()无关。 sizeof(string)=4可能是最典型的实现之一,不过也有sizeof()为28、32字节的库实现。 但是MS2015测试后sizeof(string)=40.还是跟编译器有关.

tuple大小为32而不是28的原因:tuple的大小必须是其中最大元素的倍数,complex< double>大小为16,tuple对齐后大小为32

原理

tuple原理是用可变模板参数实现的递归继承
在这里插入图片描述

this指针指向的是父类对象的位置,即head在下面,tail在前面。

type traits

type traits用法

在这里插入图片描述

type traits实现

is_void实现
在这里插入图片描述
实质上是对基本类型定义特化版本,先把volatile和const用模板特化去除掉,然后用__is_void_helper对void特化为true_type,其他泛化版本默认为false_type

类似的有is_integer
在这里插入图片描述
在复杂一点的is_move_assignable等实现中并没有找到源码,猜想是编译器帮助他们完成了底层的实现。
在这里插入图片描述

cout

在这里插入图片描述
cout是一个ostream类对象
重载输入输出运算符时要注意:
通常重载输入输出(运算符)时必须是非成员函数重载,主要是为了与iostream标准库兼容。为了与标准IO库一致,重载后的符号的左侧应该是流的引用,右侧是对象的引用。(如,cout<<“hello!”;或cin>>tmp;等。)但是如果重载为类的成员函数的话,运算符左侧是对象的引用,右侧是流的引用。(ps:事实的确如此,回想一下成员函数的重载都是对象在前运算符号在后。)也就是说其形式为:

Sales_data  data;
 
data  <<  cout;//如果operator<<是Sales_data的成员。

因此定义重载输入输出运算符中要在类中定义友元函数,如Complex类

class Complex{  
    public:
        Complex( double r=0, double i=0):real(r),imag(i){ };
        friend ostream & operator<<( ostream & os,const Complex & c);
        friend istream & operator>>( istream & is,Complex & c);
    private:
        double real,imag; 
};

在标准库中对cout的重载
在这里插入图片描述

move

详细见C++新特性(标准库)

简单来说,move assignment和move ctor只拷贝指针,再把原指针的指向对象和数据清零,为浅拷贝。拷贝构造和拷贝赋值函数需要创建一块新的空间,再将原来对象的数据添加到新空间中,为深拷贝

moveable测试函数

用到的class是C++新特性(标准库)中的move-aware-class
在这里插入图片描述

  • 其中Vltype(buf)为临时对象,insert()调用后该对象不再使用,因此会自动调用move版本的ctor。因此Mctor在初始化数据时已经调用了700w次,这是元素的copy。
  • 而在M c11(c1);时编译器不知道c1是不是临时对象,因此采用传统的copy ctor,花费了3500ms。这是容器的copy
  • 如果显式告诉编译器用move版本,即M c12(std::move(c1));,则采用Mctor。这也是容器的copy。

也可以写成模板模板参数形式

template <typename T,
          template <typename T>
              class Container
         >
class XCls
{
private:
    Container<T> c;
public:
    XCLs()
    {
        for(long i=0; i<SIZE; ++i)
            c.insert(c.end(), T());//也可以像上面一样用随机数生成
 
        output_static_data(T());//也可以像上面一样用随机数生成
        Container<T> c1(c);
        Container<T> c2(std::move(c));
        c1.swap(c2);
    }
};

//不得在function body之内声明
template<typename T>
using Vec = vector<T, allocator<T>>;
 
XCls<MyString, Vec> c1;

vector的copy ctor

在这里插入图片描述

vector的move ctor

在这里插入图片描述
对容器做move,只是swap了三根指针

std::string是否moveable?

在这里插入图片描述
string带有Move版本的assignment和ctor。

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

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

相关文章

Android 签名基础知识

目录Android 为什么要签名keystore的生成&#xff1a;keystore信息的查看参数说明&#xff1a;Android 怎么签名使用 jarsigner 签名如何查找 jdk 位置签名时遇到的问题查看 apk 是否签名查看 Apk 的MD5值以及MD5不显示时的解决办法缺少 xx.RSA 文件的原因V1 vs V2Android 为什…

Coolify系列-解决局域网主机突然连不了虚拟机

开始之前&#xff0c;我们需要确保配置一切正常&#xff0c;原始配置参考下文 Coolify系列-手把手教学解决局域网局域网中的其他主机访问虚拟机以及docker服务 如果是之前已经配置好的&#xff0c;突然无法访问了&#xff0c;采取以下方式进行排查操作 在虚拟机执行 ifconf…

【GD32F427开发板试用】基于蓝牙的远程步进电机控制

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;寒冰1988 一、前言 接上篇文章【GD32F427开发板试用】基于蓝牙模块的远程点灯演示&#xff0c;本篇是第二篇&#xff0c;基于调通的蓝牙模块添…

Pytest-Allure测试报告

Allure 模块下载 pip install allure-pytest包下载 https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/此处我选择下载最新的&#xff0c;版本上可以选择不是最新的&#xff0c;2.9.0的。下载zip或者tgz后缀格式的都可以。 配置环境变量 找到解压…

RPA自动办公01——Uibot的安装和基础用法

本期开始RPA的学习流程。 RPA是机器人自动化流程的简写&#xff0c;目的在于减少重复性的劳动&#xff0c;而且上手很简单&#xff0c;无需编程就能用。 本系列使用Uibot 软件&#xff0c;其下载地址在&#xff1a;来也科技流程创造者&#xff08;UiBot Creator&#xff09; …

searchableSelect 插件使用

<script type"text/javascript" src"//searchableSelect.js"></script> <script>function getUserServer() {var _this 自定义封装接口请求、弹窗等方法;_this.getAjax("get","//xxxxx/server", {}, function(res)…

前端异常监控平台Sentry安装配置使用及问题

前言&#xff1a;Sentry是一款开源的异常监控平台,支持各种语言的SDK&#xff0c;通过对应SDK可以收集错误信息和性能数据&#xff0c;并可以再后台web页面中查看相关信息。官方地址&#xff1a;安装说明&#xff1a;https://develop.sentry.dev/self-hosted/后台使用说明&…

1.1计算机组成结构:CPU组成、冯·诺依曼结构与哈佛结构、嵌入式芯片术语

1.1计算机组成结构&#xff1a;CPU组成、冯诺依曼结构与哈佛结构、嵌入式芯片术语计算机组成结构CPU组成运算器控制器冯诺依曼结构与哈佛结构冯诺依曼结构哈佛结构嵌入式——芯片术语计算机组成结构 CPU组成 CPU分成两个部分&#xff0c;包括运算器和控制器。 CPU是计算机中核…

Linux之环境搭建

目录 一、VMware 二、centos7的安装 三、Mysql安装 四、 前端项目部署 1.确保前台项目能用 2.将前台项目打包npm run build 3.做ip/host主机映射 4.完成Nginx动静分离的default.conf的相关配置 5.将前端构件号的dist项目&#xff0c;上传到云服务器/usr/local/... …

[Swift]SDK开发

本文主要介绍使用swift语言制作framework Demo:https://github.com/Gamin-fzym/CMSDK 一、创建工程 1.创建目录 这里我创建了一个“CMSDK”目录 2.打开Xcode新建workspace放入CMSDK目录 这里命名为“CMSDK” 3.打开CMSDK.xcworkspace新建SDK工程放入CMSDK目录 这里还是命…

06 CSS-盒子模型【尚硅谷JavaWeb教程】

06 CSS-盒子模型【尚硅谷JavaWeb教程】 JAVAWEB的学习笔记 学习视频来自&#xff1a;https://www.bilibili.com/video/BV1AS4y177xJ/?vd_source75dce036dc8244310435eaf03de4e330 不同的浏览器导致前端展示页面不一样&#xff0c;盒子的大小的不同。&#xff08;所以前端要考虑…

奇迹mu开服教程

奇迹mu开服教程&#xff1a;开服服务端的架设及开服注意事项服务器推荐奇迹开服需要准备什么&#xff1f;开服大概成本分析奇迹MU商业服务端版本&#xff1a;1.02W、1.03H、1.03K、S6EP3、S7EP2、S9EP2&#xff1b;HE网站系统&#xff1a;绑定域名授权&#xff0c;功能可定制&a…

Jenkins部署项目一(物理机器部署SpringBoot项目)

一、Jenkins部署SpringBoot项目 设备&#xff1a;MacOS 准备工作 1.已安装java开发工具包JDK 2.已安装依赖管理工具Maven 3.已安装代码版本控制工具Git 4.已安装Jenkins learn-moon代码地址&#xff1a;https://github.com/BillDavidup/learn-moon SSH: gitgithub.com:Bil…

【学Vue就跟玩一样】如何使用集中式状态管理的Vuex以及如何模块化编码+命名空间

1.vuex是什么一个专门在Vue中实现集中式状态管理的一个Vue插件,可以对vue应用中多个组件的共享状态进行集中式的管理(读取/写入)&#xff0c;也是一种组件间通信的方式&#xff0c;并且适用于任意组件间通信2.什么时候使用Vuex1.多个组件依赖于同一状态2.来自不同组件的行为需要…

Goland入门指南(使用Goland创建并运行项目)

在文章《Goland下载和安装》详细介绍了 Goland 的安装和破解&#xff0c;本节我们来介绍一下怎么使用 Goland 来创建并运行一个项目。 创建项目 首先&#xff0c;在“文件”菜单中找到“New”&#xff0c;并在下一级菜单中选择“Project”来创建一个新项目。 为项目选择一个…

【vim】C语言代码提示

前言 常见的C语言提示插件是YouCompleteMe&#xff0c;这个插件安装比较麻烦&#xff0c;在这推荐一款coc.nvim这个插件&#xff0c;github仓库地址&#xff1a;https://github.com/neoclide/coc.nvim/ 下面是安装步骤。 一、安装 nodejs 1、终端命令安装 curl -sL instal…

SpringMVC DispatcherServlet源码(2) 扫描Controller创建HandlerMapping流程

Spring MVC向容器注册一个RequestMappingInfoHandlerMapping组件&#xff0c;他会扫描容器中的Controller组件&#xff0c;创建RequestMappingInfo并注册HandlerMethod映射关系。 本文将阅读Spring MVC源码分析上述流程。 RequestMappingHandlerMapping组件 Creates Request…

java ssm校园兼职发布与互动平台的设计与实现

该系统基于B/S即所谓浏览器/服务器模式&#xff0c;应用JSP技术&#xff0c;选择MySQL作为后台数据库。系统主要包括个人中心、用户管理、企业管理、企业信息管理、兼职信息管理、职位申请管理、职位类型管理、交流中心、留言反馈、系统管理等功能模块。 使用校园兼职发布与互动…

JavaWeb:会话技术之Session

Cookie已经能完成一次会话多次请求之间的数据共享&#xff0c;之前我们还提到过Session也可以实现&#xff0c;那么&#xff1a; 什么是Session&#xff1f;Session如何来使用&#xff1f;Session是如何实现的&#xff1f;Session的使用注意事项有哪些&#xff1f; 1. Sessio…

SpringCloud学习笔记 - 熔断降级 - Sentinel

1. Sentinel熔断降级概述 1.1. 熔断降级要解决的问题 除了流量控制以外&#xff0c;对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块&#xff0c;可能是另外的一个远程服务、数据库&#xff0c;或者第三方 API 等。例如&…