C++ 内存管理和模板与STL

news2024/12/15 4:03:47

        此篇目是之后各种C++库的基础

目录

内存管理

        内存分布

        内存管理方式 

        new和delete 

         operator new 与 operator delete函数

        实现原理 

         定位new表达式(placement-new)

 模板基础

        泛型编程

        模板

        函数模板

        类模板

STL

         组成部分


内存管理

        内存分布

int globalVar = 1; //全局变量 静态区
static int staticGlobalVar = 1;//静态变量 静态区
void Test()
{
static int staticVar = 1;//静态变量 静态区
int localVar = 1;//局部变量 栈
int num1[10] = { 1, 2, 3, 4 };//局部变量 栈
char char2[] = "abcd";//局部变量 栈
const char* pChar3 = "abcd";//指针 栈 但是"abcd"是代码段(常量区)
int* ptr1 = (int*)malloc(sizeof(int) * 4);//指针 栈 指向堆
int* ptr2 = (int*)calloc(4, sizeof(int));//指针 栈 指向堆
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);//指针 栈 指向堆
free(ptr1);
free(ptr3);
}

栈                存储非静态局部变量/函数参数/返回值 向下增长

内存映射段 高效的I/O映射方式,用于装载一个共享的动态内存库

堆                程序运行时动态内存分配,向上生长

数据段         全局数据与静态数据

代码段         可执行的代码/只读的常量

        内存管理方式 

        内存管理方式有 malloc/calloc/realloc/free

  1. malloc

    • 内存来源:在堆区申请一块连续的指定大小的内存块区域。
    • 初始化:不会进行内存初始化,即分配的内存区域可能包含任意数据。
  2. calloc

    • 内存来源:与malloc类似,也是用于动态地分配内存空间。
    • 初始化:会在分配内存时自动将内存清零,即将分配的内存区域的每一位都初始化为零。因此,calloc也被称为“零初始化内存分配器”。
  3. realloc

    • 内存来源:用于重新分配之前通过malloc、calloc或realloc分配的内存块。
    • 初始化:realloc本身不会进行初始化操作,但它会调整已分配内存块的大小,并根据需要调整内存块的位置。如果重新分配的内存区域比原来的大,则新分配的部分不会进行初始化。

        但是在C++中 引入了新的内存管理方式

        new和delete 

        因为有一些方面 原始的申请会有些无力 因此C++推出了自己的申请函数

int main()
{
	int* ptr1 = new int;//申请一个int空间
	int* ptr2 = new int(10);//申请一个int空间 并初始化为10
	int* ptr3 = new int[3];//申请3个int空间 可以认为是 数组
	
	delete ptr1;//普通的就用delete删除
	delete ptr2;
	delete[] ptr3; //[]出来的要用[]删除
}

        new和delete在对自定义类型操作时 也会有不同的变化

对自定义类型操作时

        new会调用自定义类型的构造函数

        delete会调用自定义类型的析构函数

malloc和free不会去调用

class A
{
public:
	A(int num = 0) :a(num) { cout << "A()" << endl;}
	~A() { cout << "~A()" << endl;}
private:
	int a;
};

int main()
{
	A* ptra = new A(1);
	delete ptra;
	A* ptrb = new A[5];
	delete[] ptrb;
	return 0;
}

 

         operator new 与 operator delete函数

new与delete                              是用户进行内存申请和释放的 操作符

operator new与operator delete 是系统提供的                           全局函数

new    在底层 调用 operator new

delete 在底层 调用 operator delete

operator new    是通过 malloc 申请空间

operator delete 是通过 free     释放空间

        实现原理 

        new原理

        调用operator new申请空间 然后用构造函数完成对象构造

        delete原理

        调用析构函数清理对象 然后调用operator delete函数释放对象空间 

        new T[N]原理

        调用operator new[]函数,在operator new[]中调用operator new函数完成对N个对象的空间申请 然后用N此构造函数

        delete[]原理

        在要释放的对象空间上完成N次析构函数,然后对N个对象中资源的清理,然后调用operator delete[]释放空间,也就是在operator 

         定位new表达式(placement-new)

        解释

        定位new表达式是在已经分配的原始内存空间中调用构造含初始化了一个对象

        使用格式

        new (place_address)type 或者 new(place_address) type(initializer-list)

        place_address必须是一个指针initializer-list是类型的初始化列表 

         使用场景

        定位new表达式一般是配合内存池使用,因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调用构造函数进行初始化.

class A
{
public:
	A(int num = 0) :a(num) { cout << "A()"<< a;}
	~A() { cout << "~A()";}
private:
	int a;
};

int main()
{
	A* p1 = (A*)malloc(sizeof(A));
	new(p1)A;//new重定位
	p1->~A();
	free(p1);
	cout << endl;
	A* p2 = (A*)malloc(sizeof(A));
	new(p2)A(10);//new重定位 然后给初始值
	p2->~A();
	free(p2);
}

 模板基础

        泛型编程

        用函数重载实现交换函数

void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
} 
void Swap(double& left, double& right)
{
double temp = left;
left = right;
right = temp;
} 
void Swap(char& left, char& right)
{
char temp = left;
left = right;
right = temp;
}

        从例子中看到,重载的函数仅仅只是类型不同,复用成度并不高,如果出现新的类型,就需要用户自己新增,而且无法一起修正错误,往往伴随着,错一个就错一堆,那么就要用到"模板" 了

        模板

        C++中存在一个模具,根据模具中填充的不同类型,获得不同的代码,泛型编程解释编译与类型无关的通用代码,方便代码复用.

模板分 函数模板 和 类模板

        函数模板

        概念

        函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生的函数的特定类型的版本

          格式

templat<typename T1,typename T2....>

返回值 函数名 参数

template<typename T1, class T2>
void Swap(T1& left, T2& right)
{
	T1 temp = left;
	left = right;
	right = temp;
}

        原理

        通过编译器使用的特殊方式产生具体类型函数的模具,模板就是将本应该我们做的重复的事情交给了编译器 

        实例化

        隐式调用

template<typename T1, class T2>
void Swap(T1& left, T2& right)
{
	T1 temp = left;
	left = right;
	right = temp;
}
int main()
{
	int a = 1;
	double b = 2;
	Swap(a, b);
	cout << a << b << endl;
	return 0;
}

        显式调用

template<typename T1, class T2>
void Swap(T1& left, T2& right)
{
	T1 temp = left;
	left = right;
	right = temp;
}
int main()
{
	int a = 1;
	double b = 2;
	Swap<int,double>(a, b);
	cout << a << b << endl;
	return 0;
}

        模板参数匹配原则

        我称之为:最多匹配优先原则,就是匹配拟合度最高的优先被调用

        而且无论是已存在的还是模板,都是按照拟合度最高的匹配 

void Swap(int left, int right)//优先匹配 int int
{
	int temp = left;
	left = right;
	right = temp;
}

template<typename T1>//匹配 两个相同参数
void Swap(T1& left, T1& right)
{
	T1 temp = left;
	left = right;
	right = temp;
}

template<typename T1,int>//匹配 T1 和 int 优先
void Swap(T1& left, int& right)
{
	T1 temp = left;
	left = right;
	right = temp;
}

template<typename T1, class T2>//任意两个类型
void Swap(T1& left, T2& right)
{
	T1 temp = left;
	left = right;
	right = temp;
}

        类模板

        也就是 使用模板参数当作类里面参数 

             定义格式

template<class T1,class T2>
class name
{
public:
	//...
private:
	T1 _t1;
	T2 _t2:
	//...
};

        注意

        模版不建议声明和定义分离到两个文件.h 和.cpp会出现链接错误

        实例化

template<class T1,class T2>
class name
{
public:
	//...
private:
	T1 _t1;
	T2 _t2:
	//...
};
int main()
{
	name<int, int> A;
	name<int, char> B;
}

STL

        STL是C++标准库的重要组成部分,是标准模板库,不仅是一个可复用的组件库,而且是一个包含数据机构与算法的软件框架

         组成部分

        仿函数 算法 迭代器 空间配置器 容器 配接器 

        本章结言

我将会在下一章开始写 

string

vector

list

stack

queue

等基础STL的应用与实现

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

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

相关文章

深入理解 CSS 文本换行: overflow-wrap 和 word-break

前言 正常情况下&#xff0c;在固定宽度的盒子中的中文会自动换行。但是&#xff0c;当遇到非常长的英文单词或者很长的 URL 时&#xff0c;文本可能就不会自动换行&#xff0c;而会溢出所在容器。幸运的是&#xff0c;CSS 为我们提供了一些和文本换行相关的属性&#xff1b;今…

Polars数据聚合与旋转实战教程

在这篇博文中&#xff0c;我们的目标是解决数据爱好者提出的一个常见问题&#xff1a;如何有效地从Polars DataFrame中创建汇总视图&#xff0c;以便在不同时间段或类别之间轻松进行比较。我们将使用一个实际的数据集示例来探索实现这一目标的各种方法。 Polars简介 Polars 是…

STM32CUBEMX+STM32F4+IAP串口升级应用,亲测可用,带详解

一、IAP的基本概念 IAP,全名为in applacation programming,即在应用编程。 也就是在应用程序中升级。好处就太多了&#xff0c;比如远程在线升级&#xff0c;不用人到现场拆开&#xff0c;用烧写器连接升级。 实现IAP技术的核心是一段预先烧写在单片机内部的IAP程序。这段程…

CTFHub 命令注入-综合练习(学习记录)

综合过滤练习 命令分隔符的绕过姿势 ; %0a %0d & 那我们使用%0a试试&#xff0c;发现ls命令被成功执行 /?ip127.0.0.1%0als 发现一个名为flag_is_here的文件夹和index.php的文件&#xff0c;那么我们还是使用cd命令进入到文件夹下 http://challenge-438c1c1fb670566b.sa…

深入探索 JVM:原理、机制与实战

一、JVM 概述 JVM&#xff08;Java Virtual Machine&#xff09;是 Java 程序运行的核心组件&#xff0c;它提供了一个独立于硬件和操作系统的执行环境&#xff0c;使得 Java 程序能够在不同平台上具有跨平台的特性。 JVM 主要由以下几部分组成&#xff1a; 类装载器&#xf…

视频推拉流EasyDSS无人机直播技术巡查焚烧、烟火情况

焚烧作为一种常见的废弃物处理方式&#xff0c;往往会对环境造成严重污染。因此&#xff0c;减少焚烧、推广绿色能源和循环经济成为重要措施。通过加强森林防灭火队伍能力建设与长效机制建立&#xff0c;各地努力减少因焚烧引发的森林火灾&#xff0c;保护生态环境。 巡察烟火…

挺详细的记录electron【V 33.2.0】打包vue3项目为可执行程序

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、直接看效果 二、具体步骤 1.安装配置electron 1.将 electron 包安装到应用的开发依赖中。 2.安装electron-packager依赖&#xff08;打包可执行文件&#…

基本分页存储管理

一、实验目的 目的&#xff1a;熟悉并掌握基本分页存储管理的思想及其实现方法&#xff0c;熟悉并掌握基本分页存储管理的分配和回收方式。 任务&#xff1a;模拟实现基本分页存储管理方式下内存空间的分配和回收。 二、实验内容 1、实验内容 内存空间的初始化——可以由用户输…

Vue Web开发(五)

1. axios axios官方文档 异步库axios和mockjs模拟后端数据&#xff0c;axios是一个基于promise的HTTP库&#xff0c;使用npm i axios。在main.js中引入&#xff0c;需要绑定在Vue的prototype属性上&#xff0c;并重命名。   &#xff08;1&#xff09;main.js文件引用 imp…

论文概览 |《IJAEOG》2024.08 Vol.132(下)

本次给大家整理的是《International Journal of Applied Earth Observation and Geoinformation》杂志2024年08月第132期的论文的题目和摘要&#xff0c;一共包括88篇SCI论文&#xff01;由于论文过多&#xff0c;我们将通过两篇文章进行介绍&#xff0c;本篇文章介绍第45--第8…

「数据结构详解·十五」树状数组

「数据结构详解一」树的初步「数据结构详解二」二叉树的初步「数据结构详解三」栈「数据结构详解四」队列「数据结构详解五」链表「数据结构详解六」哈希表「数据结构详解七」并查集的初步「数据结构详解八」带权并查集 & 扩展域并查集「数据结构详解九」图的初步「数据结构…

【sgFileLink】自定义组件:基于el-link、el-icon标签构建文件超链接组件,支持垃圾桶删除、点击预览视频/音频/图片/PDF格式文件

sgFileLink源代码 <template><div :class"$options.name"><el-link click.stop"clickFile(data)"><img :src"getSrc(data)" /><span>{{ getFileNameAndSize(data) }}</span></el-link><el-linkcl…

电机驱动模块L9110S详解

电机驱动模块是一种用于控制和驱动电机的设备&#xff0c;它能够将控制信号转化为适合电机操作的电流和电压。通过电机驱动模块&#xff0c;可以实现对电机的速度、方向等参数进行精确控制。 今天我们要介绍的 L9110S 电机驱动适合大学生、工程师、个人DIY、电子爱好者们学习和…

Unity 获取鼠标点击位置物体贴图颜色

实现 Ray ray Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out RaycastHit hit)) {textureCoord hit.textureCoord;textureCoord.x * textureMat.width;textureCoord.y * textureMat.height;textureColor textureMat.GetPixel(Mathf.Flo…

openlayers+vite+vue3实现在地图上画线(四)

在前几期实现离线地图初始化以及规划某一特定区域、打点、出现弹窗的基础上&#xff0c;本文主要阐述如何实现在所规划的区域地图上画线&#xff0c;如果你实现了打点的效果&#xff0c;其实这个相对来说还是算比较简单的&#xff0c;因为和打点的代码大差不差。使用openlayers…

游戏引擎学习第45天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾 我们刚刚开始研究运动方程&#xff0c;展示了如何处理当人物遇到障碍物时的情况。有一种版本是角色会从障碍物上反弹&#xff0c;而另一版本是角色会完全停下来。这种方式感觉不太自然&#xff0c;因为在游戏中&#xff0c;…

类与对象以及ES6的继承

认识class定义类 类的声明用的比较多 类与构造函数的异同 类的构造函数 类的实例方法 类的访问器方法 在类里面写拦截方法 类的静态方法 通过类名直接访问 es6类的继承-extends super关键字 子类可以重写父类方法包括父类的静态方法也可以继承父类的静态方法 babel可以将新的代…

通过IKE协商方式建立IPSec隧道

我们前面学习了H3C的IPsec VPN配置&#xff08;为什么IPsec两端内网的网段能不能重复&#xff1f;分明可以实现&#xff01;&#xff09;&#xff0c;学习了Juniper的IPsec VPN配置&#xff0c;学习了Windows的IPsec VPN配置&#xff08;配置Juniper虚墙vSRX基于策略的IPsec VP…

文献分享: EMVB——PLAID后期交互引擎的进一步优化

&#x1f449;前情提要&#xff1a; 神经网络自然语言模型概述 Transformer \text{Transformer} Transformer与注意力机制概述 &#x1f4da;相关论文&#xff1a; BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding \text{BERT: Pre-train…

vue2+element-ui实现多行行内表格编辑

效果图展示 当在表格中点击编辑按钮时:点击的行变成文本框且数据回显可以点击确定按钮修改数据或者取消修改回退数据: 具体实现步骤 1. 行数据定义编辑标记 行数据定义编辑标记 当在组件中获取到用于表格展示数据的方法中,针对每一行数据添加一个编辑标记 this.list.f…