内存管理和模板

目录

定位new表达式

定位new使用的池化技术:

 ​编辑

malloc和free与new和delete的区别:

 内存泄漏:

模板

 显示实例化

两个不同参数的模板

 模板函数与函数:

 类模板

[]重载:


定位new表达式

class A
{
public:A(int a=0):_a(a){cout << "构造函数" << this << endl;}~A(){cout << "析构函数" << endl;}
private:int _a;
};int main()
{A*p1 = new A;//A*p2 = new A[10];A*p3 = (A*)malloc(sizeof(A));if (p3 == nullptr){perror("malloc fail");exit(-1);}new(p3)A(1);return 0;
}

使用场景:

已分配地址。

对对象完成初始化。

 

我们要完成释放:

 

也可以直接使用delete函数。

 

定位new使用的池化技术:

 

当我们要使用栈上的空间时,我们每一次使用堆空间都需要申请,我们可以建立一个内存池,该内存池有一部分内存,我们可以直接使用。

 对于这类可以不申请就可以使用的空间(内存池)

我们需要通过定位new来完成初始化

malloc和free与new和delete的区别:

 内存泄漏:

内存泄漏:指针丢了

指针丢了,我们就无法通过该指针释放对应空间,造成内存泄漏。

模板

#include<iostream>
using namespace std;
void Swap(int&a, int&b)
{int tmp = a;a = b;b - tmp;
}
void Swap(double&a, double&b)
{double tmp = a;a = b;b - tmp;
}
int main()
{int a = 1, b = 2;Swap(a, b);double x = 1.1, y = 2.2;Swap(x, y);return 0;
}

我们实现的两个函数功能相同,只是处理的变量类型不同,我们必须显示的定义出两个函数。

有没有办法可以只定义出一个函数实现以上操作呢?

#include<iostream>
using namespace std;
template <typename T>//void Swap(int&a, int&b)
//{
//	int tmp = a;
//	a = b;
//	b - tmp;
//}
//void Swap(double&a, double&b)
//{
//	double tmp = a;
//	a = b;
//	b - tmp;
//}
void Swap(T&a, T&b)
{T tmp = a;a = b;b = tmp;
}
int main()
{int a = 1, b = 2;Swap(a, b);double x = 1.1, y = 2.2;Swap(x, y);return 0;
}

 

我们只用了一个函数就实现了多种类型的交换。

 Swap函数调用的是我们的函数模板吗?

答:并不是,我们定义的模板可以根据调用参数的类型来实例化出不同的重载函数:

 所以我们实例化函数并不是所有的函数都实例化,我们的实例化是对所调用函数的参数进行比对来进行实例化,我们调用几种不同类型的函数,就实例化几个函数。

实例化是编译器帮助完成的。

假如我们调用不同参数类型的交换函数,会怎么样呢?

int main()
{int a = 1, b = 2;Swap(a, b);double x = 1.1, y = 2.2;Swap(x, y);Swap(a, x);return 0;
}

这里并不能发生强制类型转换,类型转换发生在赋值或者传参之间,这里是实例化期间。

template<class T>
T Add(const T&left, const T&right)
{return left + right;
}
int main()
{int a = 1, b = 2;double c = 1.1, d = 2.2;/*cout << Add(a, b) << endl;cout << Add(c,d) << endl;*/cout << Add(a, c) << endl;return 0;
}

我们用const修饰了,传参时应该可以类型转换,为什么还会报错?

因为我们的模板函数的两个参数都是T,是相同的,所以我们无法调用使用两个不同参数的函数,我们可以多加一个模板参数。

 解决方法1:

template<class T>
//template<class T2>
T Add(const T&left, const T&right)
{return left + right;
}
int main()
{int a = 1, b = 2;double c = 1.1, d = 2.2;/*cout << Add(a, b) << endl;cout << Add(c,d) << endl;*/cout << Add((double)a, c) << endl;cout << Add(a, (int)c) << endl;return 0;
}

我们在模板实例化对象之前强制类型转化。

我们去掉const会报错:

我们把a强制类型转换为double进行传参,a本身并没有发生改变,改变的是临时变量,临时变量具有常性,不能用引用来接收。

 

 显示实例化

template<class T>
//template<class T2>
T Add(const T&left, const T&right)
{return left + right;
}
int main()
{int a = 1, b = 2;double c = 1.1, d = 2.2;/*cout << Add(a, b) << endl;cout << Add(c,d) << endl;*//*cout << Add((double)a, c) << endl;cout << Add(a, (int)c) << endl;*/cout << Add<double>(a, c) << endl;cout << Add<int>(a, c) << endl;return 0;
}

两个不同参数的模板

template<class T1, class T2> 
//template<class T2>
T1 Add(const T1&left, const T2&right)
{return left + right;
}
int main()
{int a = 1, b = 2;double c = 1.1, d = 2.2;/*cout << Add(a, b) << endl;cout << Add(c,d) << endl;*//*cout << Add((double)a, c) << endl;cout << Add(a, (int)c) << endl;*/cout << Add(a, c) << endl;cout << Add(a, c) << endl;return 0;
}

模板类参数类似于函数参数。

 模板函数与函数:

int Add(int a, int b)
{return a + b;
}
template<class T>T Add(T a, T b)
{return a + b;
}
int main()
{int a = 1, b = 2;Add(1, 2);return 0;
}

同名的模板函数与函数可以同时存在。

两个函数都可以调用的前提下,我们首先调用已经显示实例化的普通函数,模板函数还需要实例化。

显示调用模板函数:

模板函数与同名函数可以同时存在的原因:

 

两个函数虽然同名,但是他们的函数名修饰规则不同。

 类模板

template<class T>
class Stack
{
public:Stack(int capacity = 4){_a = (T*)malloc(sizeof(T)*capacity);if (_a == nullptr){perror("malloc fail");exit(-1);}_top = 0;_capacity = capacity;}void Push(const T& x){_a[_top++] = x;}~Stack(){free(_a);_a = nullptr;_top = _capacity = 0;}
private:T*_a;size_t _capacity;size_t _top;
};
int main()
{Stack<int> s1(10);s1.Push(2);Stack<double> s2(20);s2.Push(3.3);return 0;
}

注意这两个类并不是同一个类型。

因为他们所占空间大小不同,int占4个字节,double占8个字节。

[]重载:

#define N 10
template<class T>
class Array
{
public:T&operator[](size_t i){return _a[i];}
private:T _a[N];
};
int main()
{Array <int> a1;a1[1] = 10;cout << a1[1] << endl;return 0;
}

 

并且我们知道,访问数组时容易出现越界而没有报错的情况,我们可以在这个重载函数中实现绝对检查:

 

我们也可以加上内联,提升效率。

inline T&operator[](size_t i){/*	assert(i < 10);*/return _a[i];}

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

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

相关文章

大数据时代,数据治理

一、大数据时代还需要数据治理吗&#xff1f; 数据平台发展过程中随处可见的数据问题 大数据不是凭空而来&#xff0c;1981年第一个数据仓库诞生&#xff0c;到现在已经有了近40年的历史&#xff0c;相对数据仓库来说我还是个年轻人。而国内企业数据平台的建设大概从90年代末…

ToBeWritten之攻击者模拟

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

Word | 简单可操作的快捷公式编号、右对齐和引用方法

1. 问题描述 在理工科论文的写作中&#xff0c;涉及到大量的公式输入&#xff0c;我们希望能够按照章节为公式进行编号&#xff0c;并且实现公式居中&#xff0c;编号右对齐的效果。网上有各种各样的方法来实现&#xff0c;操作繁琐和简单的混在一起&#xff0c;让没有接触过公…

路由综合实验

RIP配置 在R1上配置 rip 1 #此处的1表示进程号&#xff0c;非版本号 version 2 #选择rip版本2 network 100.0.0.0 network 12.0.0.0 network 13.0.0.0 #rip宣告时只能宣告主类网络&#xff0c;实际上是对内宣告为主类网络&#xff0c;对外转发时时携带子网掩码的在R2上…

【postgresql】 ERROR: multiple assignments to same column “XXX“

Cause: org.postgresql.util.PSQLException: ERROR: multiple assignments to same column "XXX"; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: multiple assignments to same column "XXX"; 原因&#xff1a;or…

Java开发需要的网络基础知识,搞清楚计算机网络底层原理

作者&#xff1a;逍遥Sean 简介&#xff1a;一个主修Java的Web网站\游戏服务器后端开发者 主页&#xff1a;https://blog.csdn.net/Ureliable 觉得博主文章不错的话&#xff0c;可以三连支持一下~ 如有需要我的支持&#xff0c;请私信或评论留言&#xff01; 前言 计算机基础是…

变电站运维服务方案

一、背景与目标 随着电力行业的快速发展&#xff0c;变电站的数量和规模不断扩大&#xff0c;运维服务的需求也日益增长。为了确保变电站的安全、稳定、高效运行&#xff0c;提高运维服务质量&#xff0c;本文档旨在提供一套全面的变电站运维服务方案。 二、服务范围 …

lv5 嵌入式开发-6 线程的取消和互斥

目录 1 线程通信 – 互斥 2 互斥锁初始化 – pthread_mutex_init 3 互斥锁销毁 pthread_mutex_destroy 4 申请锁 – pthread_mutex_lock 5 释放锁 – pthread_mutex_unlock 6 读写锁 7 死锁的避免 8 条件变量&#xff08;信号量&#xff09; 9 线程池概念和实现 9.1 …

CCS介绍

CCS介绍 设置主体颜色 修改字体的颜色和大小 安装一些插件 CCS中的App中心 切换工作空间 导入工程

el-table-column默认选中一个复选框和只能单选事件

表格代码 <el-table ref"contractTable" v-loading"loading" :data"contractList" selection-change"contractSelectionChange" style"margin-top: 10%;"><el-table-column type"selection" width"…

【分享】Word文档如何批量转换成PDF?

Word格式比较容易编辑&#xff0c;是工作中经常用到的文档工具&#xff0c;有时候为了避免文档在传送中出现乱码&#xff0c;或者防止被随意更改&#xff0c;很多人会把Word文档转换成PDF&#xff0c;那Word文档要怎样转成PDF呢&#xff1f;如果Word文档很多&#xff0c;有没有…

uniapp获取一周日期和星期

UniApp可以使用JavaScript中的Date对象来获取当前日期和星期几。以下是一个示例代码&#xff0c;可以获取当前日期和星期几&#xff0c;并输出在一周内的每天早上和晚上&#xff1a; // 获取当前日期和星期 let date new Date(); let weekdays ["Sunday", "M…

云安全【阿里云ECS攻防】

关于VPC的概念还请看&#xff1a;记录一下弹性计算云服务的一些词汇概念 - 火线 Zone-安全攻防社区 一、初始化访问 1、元数据 1.1、SSRF导致读取元数据 如果管理员给ECS配置了RAM角色&#xff0c;那么就可以获得临时凭证 如果配置RAM角色 在获取ram临时凭证的时候&#xff…

Three.js后期处理简明教程

后期处理&#xff08;Post Processing&#xff09;通常是指对 2D 图像应用某种效果或滤镜。 在 THREE.js 中我们有一个包含一堆网格物体的场景。 我们将该场景渲染为 2D 图像。 通常&#xff0c;该图像会直接渲染到画布中并显示在浏览器中&#xff0c;但我们可以将其渲染到渲染…

人机逻辑中的家族相似性与非家族相似性

维特根斯坦的家族相似性理论是他在《哲学研究》中提出的一个重要概念。他认为&#xff0c;语言游戏是一种人们使用语言的方式&#xff0c;不同的语言游戏之间可能存在相似性&#xff0c;就像一个家族的成员之间存在相似性一样。维特根斯坦认为&#xff0c;相似性不是通过一个共…

Quartz 体系结构

Quartz的体系结构 Quartz的重要组件 Scheduler 用于与调度程序交互的主程序接口。 Scheduler调度程序-任务执行计划表&#xff0c;只有安排进执行计划的任务Job&#xff08;通过scheduler.scheduleJob方法安排进执行计划&#xff09;&#xff0c;当它预先定义的执行时间到了的时…

mac 解决 vscode 权限不足问题,Insufficient permissions

commod 空格&#xff0c;输入终端并打开写入指令 sudo chown -R xxxxxx1 xxxxx2&#xff08;例如我的sudo chown -R admin Desktop&#xff0c;具体参数查看下方&#xff09; x1: 用户名&#xff0c;可通过左上角查看 x2: 目标文件夹。可以另起一个终端&#xff0c;用cd 和 l…

Unity当中的灯光类型

文章目录 前言一、Directional平行光二、Point点灯三、Spot 聚光灯四、Area面光灯&#xff0c;只用于烘培 前言 Unity当中的灯光类型 一、Directional平行光 Unity当中最重要的灯管类型&#xff0c;类似现实中的太阳光 二、Point点灯 类似现实中的灯泡&#xff0c;萤火虫&a…

内存对齐--面试常问问题和笔试常考问题

1.内存对齐的意义 C 内存对齐的主要意义可以简练概括为以下几点&#xff1a; 提高访问效率&#xff1a;内存对齐可以使数据在内存中以更加紧凑的方式存储&#xff0c;从而提高了数据的访问效率。处理器通常能够更快地访问内存中对齐的数据&#xff0c;而不需要额外的字节偏移计…

oracle

title: “Oracle” createTime: 2021-12-13T16:35:4108:00 updateTime: 2021-12-13T16:35:4108:00 draft: false author: “name” tags: [“oracle”] categories: [“db”] description: “测试的” 时间字段分析 timestamp 精确到秒后面6位 createTime: 2021-12-13T16:35:…