类型转换-空间配置器

news2024/11/24 9:34:20

文章目录

    • 类型转换
      • C语言的类型转换
          • 隐式类型转换:
          • 强制类型的转换:
          • C类型转换缺点
      • C++强制类型转换
          • static_cast
          • reinterpret_cast
          • const_cast
          • dynamic_cast
        • explicit
    • 空间配置器(STL专用内存池)
        • SGI-STL空间配置器实现原理
          • 一级空间配置器
          • 二级空间配置器
          • 内存池
          • SGI-STL中二级空间配置器设计
        • 空间配置器应用(list)
        • 空间配置器应用(list)

类型转换

C语言的类型转换

在C语言中,如果赋值运算符左右两端类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化.

C/C++,java,Python等都是强类型的语言。js是弱类型的语言。

隐式类型转换:

编译器在编译阶段自动进行,能转就转,不能转就编译失败 .

相近的类型意义相似的类型。int->char short只是不一般大,都是表示数据大小的。像指针就不能转换成整数,意义都不一样。

如果两运算操作数数的类型不一样,会进行截断,有符号碰到无符号就会升级为无符号类型。

强制类型的转换:

需要用户自己处理.

C类型转换缺点

C风格的转换格式很简单,但是有不少缺点的:

  1. 隐式类型转化有些情况下可能会出问题:比如数据精度丢失
  2. 显式类型转换将所有情况混合在一起,代码不够清晰

因此C++提出了自己的类型转化风格,注意因为C++要兼容C语言,所以C++中还可以使用C语言的转化风格.为了加强类型转换的可视性,引入四种命名的强制类型转换符。

C++强制类型转换

static_cast

相近类型转换.用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast,但是必须是相近类型,不相关的不可以.

int main()
{
	double d = 12.34;
	int a = static_cast<int>(d);
	cout << a << endl;//12
	return 0;
}
reinterpret_cast

通常为操作数的位模式提供较低层次的重新解释,将一种类型转化为另一种不同的类型。

int a=10;	
int* p = reinterpret_cast<int*>(a);

typedef void (*Func)();
int DoSomething()
{
	cout << "DoSomething()" << endl;
	return 1;
}
int main()
{
    //下面转换函数指针的代码是不可移植的,所以不建议这样用
	Func pf = reinterpret_cast<Func>(DoSomething);
	pf();
}
const_cast

某种意义上删除了const修饰的变量不能修改的属性,const修饰的是常变量const属性去掉后小心被修改。

const 修饰的常变量直接打印

void test()
{
	volatile const int a = 2;//告诉编译器不要优化3,3
	//const int a = 2;//在栈,不在常量区(不让修改因为指令信息也在那里)
	int* p = const_cast<int*>(&a);
	*p = 3;
	cout << a << endl;//2
	//源于编译器优化,取值的时候并没有从内存取而是从之前压栈的地方取
	cout << *p << endl;//3
	//实际的内存值已经发生了改变
}
int main()
{
	test();
}
dynamic_cast

用于将父类对象指针/引用转换为子类指针/引用(动态转换)。

  • 向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)

  • 向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)

注意:

  1. dynamic_cast只能用于含有虚函数的类
  2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0

对象是不允许转的。指针和引用可以,父类必须实现多态,或在虚表上面标识是父类还是子类,不是虚函数就没有虚表.

class A
{
public:
	virtual void f() {}
};
class B :public A
{
public:
	int _b = 0;
};

//pa指向父类对象或则子类对象
void func(A* pa)
{
	//如果pa指向父类对象那么不做任何处理
	//如果指向子类对象,那么转回子类并且访问子类的对象
	//dynamic_cast 如果指向子类对象就转换成功
	//				如果指向父类对象就转换失败返回nullptr
	B* pb1 = dynamic_cast<B*> (pa);
	if (pb1 == nullptr)
	{
		cout << "转换失败" << endl;
	}
	else
	{
		cout << "pb1:" << pb1 << endl;
		pb1->_b++;
	}

}
int main()
{
	A a;
	B b;
	func(&a);
	func(&b);
	//test();
}

四种类型转换的意义:不要再用C的隐士类型转换和强制类型转换,而且全部使用规范的,实际中嫌麻烦项目中不用,很多公司写进了文档规范,谷歌。

explicit

explicit关键字阻止经过转换构造函数进行的隐式转换的发生

class A1
{
public:
	explicit A1(int a)
	{
		cout << "A1(int a)" << endl;
	}
	A1(const A1& a)
	{
		cout << "A1(const A& a)" << endl;
	}
private:
	int _a;
};
int main()
{
	A1 a1(1);//success 形参匹配
	// 隐式转换-> A tmp(1); A a2(tmp);
	A1 a2=1;//error 默认隐士类型转换
}

空间配置器(STL专用内存池)

前面在模拟实现vector、list、map、unordered_map等容器时,所有需要空间的地方都是通过new申请的,虽然代码可以正常运行,但是有以下不足之处,

  • 空间申请与释放需要用户自己管理,容易造成内存泄漏
  • 频繁向系统申请小块内存块,容易造成内存碎片
  • 频繁向系统申请小块内存,影响程序运行效率
  • 直接使用mallocnew进行申请,每块空间前有额外空间浪费
  • 申请空间失败怎么应对
  • 代码结构比较混乱,代码复用率不高
  • 未考虑线程安全问题

容器通常去堆去申请大量小块内存,需要内存的只有容器.所以空间配置器的作用:

  1. 效率问题:空间配置器就是个专用的内存池,STL就是自己用的蓄水池。

  2. 缓解内存碎片,有足够的内存但是内存中间没有还回来部分间隔开了,空间碎片化,在下一次申请大内存连续的空间的时候申请不出来。

SGI-STL空间配置器实现原理

以上提到的几点不足之处,最主要还是:频繁向系统申请小块内存造成的。那什么才算是小块内存?SGI-STL以128作为小块内存与大块内存的分界线,将空间配置器其分为两级结构,一级空间配置器处理大块内存,二级空间配置器处理小块内存.

一级空间配置器

image-20230418191439529

就是对malloc进行一次封装:

image-20230418191648133

二级空间配置器

二级空间配置器专门负责处理小于128字节的小块内存。

  • 如何才能提升小块内存的申请与释放的方式呢?

SGISTL采用了内存池的技术来提高申请空间的速度以及减少额外空间的浪费,采用哈希桶的方式来提高用户获取空间的速度与高效管理 .

image-20230418190009812

内存池

先申请一块比较大的内存块已做备用,当需要内存时,直接到内存池中去去,当池中空间不够时,再向内存中去取,当用户不用时,直接还回内存池即可。避免了频繁向系统申请小块内存所造成的效率低、内存碎片以及额外浪费的问题 .

哈希桶,大于128字节就去调用一级配置器,小于128就在对应大小的哈希桶中拿空间。

image-20230418192230526

SGI-STL中二级空间配置器设计

SGI-STL中的二级空间配置器使用了内存池技术,但没有采用链表的方式对用户已经归还的空间进行管理(因为用户申请空间时在查找合适的小块内存时效率比较低),而是采用了哈希桶的方式进行管理。

  • 为什么要设计成哈希表?而不是直接在一大块空间中申请和归还?用链表连接

哈希表的意义就是方便O(1)的方式查找,单给一个内存池管理直接切很方便,但是容器删除数据归还内存就不如哈希桶。如果是现在的设计就只能把发出去的不同大小的内存块用指针连接起来形成链表,但是要在去链表中查找大小对应的内存块,效率就太低了.所以内存块哈希表就是方便管理归还内存的.

最小一个是8字节,前一个内存块中足以存的下同一个桶中下一块的地址。对应一个的哈希桶中内存块有空间就用,没有空间就去一个大块内存中找多个对应大小的内存块,给他一个,自己再将剩下的挂起来,然后如果大内存中也没有了,那就去堆上开辟新的大内存。

  • 进程结束的时候页表销毁了,对应的挂起的内存空间也就释放了。

空间配置器应用(list)

image-20230418194836767
方便管理归还内存的.

最小一个是8字节,前一个内存块中足以存的下同一个桶中下一块的地址。对应一个的哈希桶中内存块有空间就用,没有空间就去一个大块内存中找多个对应大小的内存块,给他一个,自己再将剩下的挂起来,然后如果大内存中也没有了,那就去堆上开辟新的大内存。

  • 进程结束的时候页表销毁了,对应的挂起的内存空间也就释放了。

空间配置器应用(list)

在这里插入图片描述

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

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

相关文章

stm32启动过程(以F1为例)

文章目录 STM32启动模式STM32启动过程&#xff08;以内部flash启动为例&#xff09;启动文件功能启动文件常用汇编指令及说明 STM32启动模式 M3/M4/M7等内核复位后&#xff0c;做的第一件事&#xff1a; 从地址 0x0000 0000 处取出 堆栈指针 MSP 的初始值&#xff0c;该值为栈…

接踵而至,昆仑万维天工大语言模型发布

目录 天工大语言模型对标GPT3.5对话能力多模态应用同行对比后言 天工大语言模型 国产ChatGPT再次迎来新成员&#xff0c;4月17日下午&#xff0c;昆仑万维正式发布千亿级大语言模型“天工”&#xff0c;同时宣布即日起启动邀请测试&#xff0c;并注册了chatgpt.cn作为域名。天…

认真复习c语言1

最近好好写总结了&#xff08;不能在偷懒了&#xff09;&#xff1a;这一次绝对认真&#xff0c;写总结写了三个多小时&#xff0c;学了一个小时左右TAT&#xff1b; 今天来复习一下c语言的多文件操作&#xff1a; 经过我这几天的摸索&#xff0c;我算是明白了&#xff1a; …

Typora (windows/MacOs版) 你未曾见过的Markdown编辑器

简介 Typora的设计理念非常人性化&#xff0c;与传统编辑器相比&#xff0c;更注重用户的视觉效果和阅读体验。它的编辑界面非常简洁&#xff0c;用户可以就近编辑&#xff0c;随时查看效果&#xff0c;避免频繁地转换预览模式&#xff0c;提高了工作效率和灵活性。 此外&…

d2l解码编码器与seq2seq

seq2seq难死了&#xff0c;卡了好久&#xff0c;好不容易有些头绪了。。。 目录 1.编码器与解码器 1.1原理 1.2实现 2.seq2seq 2.1构造编码器 2.2构造解码器 repeat与cat探索 总结nn.rnn\GRU\LSTM输入输出 看一下解码器的输出 2.3损失计算 2.4训练 2.5预测 2.6预…

【C++】多态---上( 概念、条件及性质)

来前言&#xff1a; 我们之前提到过&#xff0c;C是一门面向对象的语言&#xff0c;它有三大特性——封装、继承、多态。 封装和继承我们已经详细学习过了&#xff0c;本章将进入多态的学习。 目录 &#xff08;一&#xff09;多态的概念 &#xff08;二&#xff09;多态的定…

Vector - CAPL - Panel面板_02

Button 功能&#xff1a;触发指定的操作 说明&#xff1a;Button 是一个控件&#xff0c;使用它可以触发指定的操作。 适用场景&#xff1a; 1、按下启动按钮会使电机启动。 2、启动锁定开关时&#xff0c;所有车门都会自动锁定。 3、启动TestModule测试模块、回放模块等 设…

单机部署MongoDB

文章目录 一、Windows 环境1.1 安装1.2 启动和连接1.3 Compass 图形化客户端 二、Linux 环境2.1 安装2.2 启动和连接 提示&#xff1a;以下是本篇文章正文内容&#xff0c;MongoDB 系列学习将会持续更新 一、Windows 环境 1.1 安装 ①下载安装包&#xff0c;官方下载地址&am…

OldWang带你了解MySQL(七)

文章目录&#x1f525;多表查询&#x1f525;SQL92标准中的查询&#x1f525;非等值连接&#x1f525;自连接&#x1f525;SQL99标准中的查询&#x1f525;SQL99中的自然连接(NATURAL JOIN)&#x1f525;SQL99中的内连接(INNER JOIN)&#x1f525;外连接查询(OUTER JOIN)&#…

行业那么多,为什么计算机领域这么火?

行业那么多&#xff0c;为什么计算机领域这么火&#xff1f;计算机领域火已经不是一天两天了&#xff0c;从开始的进入互联网时代、到“互联网”、再到大数据、人工智能时代、数字化经济……计算机技术从行业内部的自我发展逐渐渗透到各行各业&#xff0c;甚至成为社会整体经济…

NLP深度网络中self.embedding(x)词嵌入后降维方法

在自然语言处理中的循环神经网络中&#xff0c;经常使用torch定义类&#xff0c;self.embedding(x&#xff09;中&#xff0c;x是输入&#xff0c;介绍self.embedding(x&#xff09;返回结果&#xff0c;以及结果的形状&#xff0c;并解释这个形状 在自然语言处理中的循环神经网…

P4158 [SCOI2009]粉刷匠(分组背包问题+前缀和优化)

[TOC](P4158 [SCOI2009]粉刷匠(分组背包问题)) 一、问题 [SCOI2009]粉刷匠 题目描述 windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。 windy每次粉刷&#xff0c;只能选择一条木板上一段连续的格子&#xff0c;然后涂上一种颜色。 …

Spring Cloud Gateway: 网关

文章目录 网关Hello world路由: Route谓词: Predicate过滤器: FilterGateway实现限流: RequestRateLimiter过滤器使用Gateway实现服务降级 自定义全局过滤器GateWay中执行流程 网关 API网关就是实现了前端项目和服务端项目之间的统一入口 Nginx实现的是用户和前端项目之间调用…

【Linux】环境变量相关笔记

文章目录 echo $PATHexport和环境变量相关的命令main(int argc,char* argv[],char *env[])三个参数介绍getenv()通过系统调用获取su与su - 的区别&#xff1a;exportsource 和 .优先级 echo $PATH 是用来查环境变量的 export 从下面的图片当中可以看到&#xff0c;的确是将文…

ubuntu 20.04设置开机自启动脚本

1 建立开机启动服务 在 路径下 /lib/systemd/system/rc-local.service 的 rc-local.service 的脚本&#xff0c;内容规定了 rc.local 的启动顺序和行为 这行代码规定了这个service在开机启动时所执行的命令是&#xff1a;/etc/rc.local start。即运行 /etc/rc.local 脚本。不过…

《面试1v1》HashMap

没有人比中国人更懂 HashMap 我是 javapub&#xff0c;一名 Markdown 程序员从&#x1f468;‍&#x1f4bb;&#xff0c;八股文种子选手。 面试官&#xff1a;HashMap 是Java程序员用得最频繁的集合之一,可以给我简单介绍一下它的内部实现机制吗? 候选人&#xff1a; Hash…

C++ -3- 类和对象 (中) | 拷贝构造函数 赋值运算符重载

文章目录 4.拷贝构造函数什么是拷贝构造函数&#xff1f;应用——示例&#xff1a;日期计算器什么情况下需要自己实现拷贝构造函数&#xff1f; 5.赋值运算符重载运算符重载&#xff08;重要&#xff09;赋值运算符重载 拷贝构造函数和赋值重载函数 4.拷贝构造函数 什么是拷贝…

Baumer工业相机堡盟工业相机如何联合BGAPI SDK和OpenCV实现Mono12和Mono16格式位深度的图像保存(C++)

Baumer工业相机堡盟工业相机如何联合BGAPI SDK和OpenCV实现Mono12和Mono16位深度的图像保存&#xff08;C&#xff09; Baumer工业相机Baumer工业相机保存位深度12/16位图像的技术背景代码案例分享1&#xff1a;引用合适的类文件2&#xff1a;BGAPI SDK在图像回调中联合OpenCV保…

Effective C++条款条款42:了解typename的双重意义(Understand the two meanings of typename)

Effective C条款条款42&#xff1a;了解typename的双重意义&#xff08;Understand the two meanings of typename&#xff09; 条款42&#xff1a;了解typename的双重意义1、从属名称和非从属名称2、typename在traits机制中的运用3、牢记 总结 《Effective C》是一本轻薄短小的…

1.17 从0开始学习Unity游戏开发--场景切换

前面的所有文章我们都在一个固定的游戏场景内进行开发&#xff0c;在最开始介绍场景这个概念的时候就已经提及&#xff0c;这个场景可以是一张地图&#xff0c;或者是一个对战房间等等&#xff0c;所以显然这个场景可以有多个&#xff0c;并且可以从一个场景切换到另外一个场景…