内存管理下及模板初阶

news2025/1/22 22:57:12

在这里插入图片描述

嗨喽,今天阿鑫给大家带来内存管理下以及模板初阶的博客,下面让我们开始今天的学习吧!

内存管理下及模板初阶

  1. new和delete的实现原理
  2. 定位new表达式(placement-new)
  3. 常见面试题
  4. 泛型编程
  5. 函数模板
  6. 类模板

1. new和delete的实现原理

1.1 内置类型

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申
请空间失败时会抛异常,malloc会返回NULL。

1.2 自定义类型

new的原理:
1.调用operator new函数申请空间
2.在申请的空间上执行构造函数,完成对象的构造

delete的原理:
1.在空间上执行析构函数,完成对象中资源的清理工作
2.调用operator delete函数释放对象的空间

new T[N]的原理
1.调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
象空间的申请
2.在申请的空间上执行N次构造函数

delete[]的原理
1.在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2.调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
在这里插入图片描述

当采用new T[ ]时,会多开四个字节的一个空间,但是返回的是P2指针,只有正确调用delete[ ]才能正确进行资源的清理

2.定位new表达式(placement-new)

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
使用格式:

new (place_address) type或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表

使用场景:

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

using namespace std;
class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
	private:
		int _a;
};

int main()
{
	//A* p1 = (A*)operator new(sizeof(A));
	//new(p1)A;//显示调用构造

	A* p1 = new A[10]{ 0,1,2,3,4,5,6,7,8,9 };
	delete[]p1;//直接调用new和delete

	//**将new拆成operator new+new(指针)类型(显示调用构造函数)**
	A* p = (A*)operator new(sizeof(A));
	new(p)A(5);
	p->~A();
	operator delete(p) ;

	A* p2 = (A*)operator new[](sizeof(A) * 10);
	for (int i = 0; i < 10; ++i)
	{
		new(p2 + i)A(i);
	}
	for (int i = 0; i < 10; ++i)
	{
		(p2 + i)->~A();
	}
	operator delete[](p2);
	return 0;
}

3.常见面试题

3.1 malloc/free和new/delete的区别

malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:
1.malloc和free是函数,new和delete是操作符
2.malloc申请的空间不会初始化,new可以初始化
3.malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可,
如果是多个对象,[]中指定对象个数即可
4.malloc的返回值为void, 在使用时必须强转*,new不需要,因为new后跟的是空间的类型
5.malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需
要捕获异常
6.申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new
在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

4.泛型编程

//泛型编程
template<typename T>

void Swap(T& a, T& b)
{
	T tmp = a;
	a = b;
	b = tmp;
}

5.函数模板

5.1函数模板概念

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

5.2 函数模板格式

template<typename T1, typename T2,…typename Tn>
返回值类型 函数名(参数列表){}

5.3函数模板实例化

1.显示实例化

//显示实例化
int main()
{
	int a1 = 10, b1 = 20;
	double c1 = 10.1, d1 = 20.2;
	Add(a1, b1);
	Add(c1, d1);
cout << Add<int>(a1, c1) << endl;//c1隐式类型转换城int
cout << Add<double>(b1, d1) << endl;

5.4函数模板的匹配原则

1.都有的情况,优先匹配普通函数+参数匹配(成品+口味对)
2.没有普通函数,优先匹配参数匹配+函数模版(半成品+口味对)
3.只有一个,类型转换一下也能用,也可以匹配调用(口味不对,将就一下也行)

int Add(const int& left, const int& right)
{
	cout << "(const int& left, const int& right)" << endl;
	return left + right;
}

template<class T>
T Add(const T& left, const T& right)
{
	cout << "(const T& left, const T& right)" << endl;
	return left + right;
}

template<class T1,class T2>

auto Add(const T1& left, const T2& right)
{
	cout << "(const T1& left, const T2& right)" << endl;
	return left + right;
}

int main()
{
	int a1 = 10, b1 = 20;
	double c1 = 10.1, d1 = 20.2;
	Add(a1, b1);
	/*Add(c1, d1);*/

	//显示实例化
	cout << Add<int>(a1, c1) << endl;//c1隐式类型转换城int
	cout << Add<double>(b1, d1) << endl;
	//显示实例化,当两个参数类型不同时,使它有机会调用第一个模板



	cout << Add(a1, d1) << endl;
	return 0;
}

6.类模板

6.1类模板

template<class T>
class Stack
{
public:
	Stack(size_t capacity = 3)
		//会先初始化列表初始化成员变量
	{
		cout << "Stack(size_t capacity = 3)" << endl;
		_array = (T*)malloc(sizeof(T) * capacity);
		if (_array == NULL)
		{
			perror("malloc failed");
			return;
		}
		_capacity = capacity;
		_size = 0;
	}
	void Push(const T& x);
	
	~Stack()
	{
		cout << "~Stack()" << endl;//用来检验有没有调用析构函数

		if (_array)
		{
			free(_array);
			_array = NULL;
			_capacity = 0;
			_size = 0;
		}
	}
	Stack(Stack& st1)
	{   //进行深拷贝,空间和内容都要相同
		_array = (T*)malloc(sizeof(T) * st1._capacity);
		if (_array == NULL)
		{
			perror("malloc failed");
			return;
		}
		memcpy(_array, st1._array, sizeof(T) * st1._size);
		_capacity = st1._capacity;
		_size = st1._size;


	}

private:
	T* _array;
	int _capacity;
	int _size;
};

6.2类模板声明与定义分离

void Stack<T>::Push(const T& x)//类型为Stack<T>
{
	// CheckCapacity();
	_array[_size] = x;
	_size++;
}

模板不建议声明与定义分离到.h和.cpp,会出现链接错误。

好啦,今天的博客就介绍到这里啦!觉得博主写的不错的,记得留下你的三连哦,谢谢你的支持!

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

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

相关文章

上位机工作感想-从C#到Qt的转变-1

0.前言 接触Qt开发也有一年多的时间了&#xff0c;还记得去年初从杭州回合肥时&#xff0c;刚来公司面临的几个问题&#xff1a; 1.C#转上位机的迷茫2.新公司管理模式的差异3.试用期的各种紧急任务。 当时也是加班加点学习C和Qt的基础知识&#xff0c;做了两个考核项目后&am…

Hadoop——Yarn 生产环境核心参数

1. ResourceManager 相关参数&#xff1a; yarn.resourcemanager.hostname&#xff1a;ResourceManager 的主机名。yarn.resourcemanager.webapp.address&#xff1a;ResourceManager 的 Web 应用程序地址。yarn.resourcemanager.scheduler.address&#xff1a;ResourceManage…

MB21屏幕增强

MB21 增强 一、屏幕抬头增强 需要在屏幕的抬头添加两个字段&#xff0c;并将字段保存至自建表 二、增强步骤 首先屏幕中的收货字段找到对应的屏幕为0521。 在对应的屏幕添加增强的字段&#xff1a;命名需要和对应的表名一样 根据需求&#xff0c;增强只针对预留中的异动…

华为机考入门python3--(16)牛客16-购物单最大满意度

分类&#xff1a;动态规划&#xff0c;组合&#xff0c;最大值&#xff0c;装箱问题 知识点&#xff1a; 生成递减数 100, 90, 80, ..., 0 range(100, -1, -10) 访问列表的下标key for key, value in enumerate(my_list): 动态规划-捆绑装箱问题 a. 把有捆绑约束的物…

SpringMvc的核心组件和执行流程

一、 springmvc的核心组件及作用 1.DispatcherServlet:前置控制器&#xff0c;是整个流程控制的核心&#xff0c;用来控制其他组件的执行&#xff0c;降低了其他组件的耦合性 2.Handler:控制器&#xff0c;完成具体的业务逻辑&#xff0c;当DispatcherServlet接收到请求后&am…

力扣70:爬楼梯(经典动态规划)

题目 解题思路 考虑动态规划&#xff0c;dp[i]表示爬到第i层的方法种数&#xff0c;对于第i层&#xff0c;可以从第i-2层爬两个台阶到达&#xff0c;也可以从i-1层爬一个台阶到达&#xff0c;故dp[i]dp[i-1]dp[i-2]&#xff0c;输出dp[n]即为答案 代码 #include<iostream…

CSS——高级选择器

层次的选择器&#xff1a; <1> 后代选择器&#xff1a; 格式&#xff1a; 标签1 标签2{} 解释&#xff1a; 标签1 不生效&#xff0c;被标签1 嵌套中的 标签2才生效 举例&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charse…

利用fft算法理解频率和像素变化率的关系

算法我就不贴了。算法就是算法导论的内容。 我直接写推导过程。 假设变化率为f(n1)-f(n) 首先计算二进制数&#xff0c;这里我假设为3位二进制。 例如:f(5)-f(4)&#xff0c; 5和4的二进制为101,100。所以逆序数为101&#xff0c;001 101对应的频率为5, 001对应的频率为1…

go | defer、panic、recover

刷一道题&#xff0c; 将当函数触发panic 之后&#xff0c;函数是怎么执行的 然后我去找相关博客&#xff0c;发现这篇讲的蛮好的 接下来我直接上demo &#xff0c;然后通过demo 来逐个分析 package mainimport ("fmt" )func f() {defer func() {if r : recover();…

【 AIGC 研究最新方向(上)】面向平面、视觉、时尚设计的高可用 AIGC 研究方向总结

目前面向平面、视觉、时尚等设计领域的高可用 AIGC 方向有以下 4 种&#xff1a; 透明图层生成可控生成图像定制化SVG 生成 本篇&#xff08;上篇&#xff09;介绍 1、2&#xff0c;而下篇将介绍 3、4。 透明图层生成 LayerDiffuse 代表性论文&#xff1a;Transparent Imag…

23种设计模式之抽象工厂

简单工厂和工厂方法 关注 产品等级 抽象工厂 关注 产品族 对于比较稳定的产品&#xff0c;抽象工厂更有效率&#xff08;一个工厂生产很多产品族&#xff09; 抽象工厂代码例子加深理解

数组的删除与插入优化思路

数据结构&#xff1a;线性表、非线性表 线性表&#xff1a; 数组&#xff0c;链表、队列、栈等。 线性表就是数据排成像一条线一样的结构&#xff0c;每个线性表上的数据最多只有前和后两个方向。 非线性表&#xff1a; 二叉树、堆、图等。 在非线性表中&#xff0c;数据之间并…

09 JavaScript学习:对象

对象的概念 在计算机科学中&#xff0c;对象是一种数据结构&#xff0c;用于存储数据和方法&#xff08;也称为函数&#xff09;。对象可以包含属性&#xff08;也称为成员变量&#xff09;和方法&#xff08;也称为成员函数&#xff09;&#xff0c;通过这些属性和方法可以描述…

SpringMVC--RESTful

1. RESTful 1.1. RESTful简介 REST&#xff1a;Representational State Transfer&#xff0c;表现层资源状态转移。 RESTful是一种网络架构风格&#xff0c;它定义了如何通过网络进行数据的交互。这种风格基于HTTP协议&#xff0c;使得网络应用之间的通信变得更加简洁和高效。…

每天五分钟机器学习:神经网络模型参数的选择

本文重点 在深度学习和人工智能的浪潮中,神经网络作为其中的核心力量,发挥着举足轻重的作用。然而,神经网络的性能并非一蹴而就,而是需要经过精心的参数选择和调优。 神经网络由大量的神经元组成,每个神经元之间通过权重进行连接。这些权重,以及神经元的偏置、激活函数…

CSS基础:position定位的5个类型详解!

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合…

《R语言与农业数据统计分析及建模》学习——数据框的统计处理

1、数据框的透视 aggregate()函数用于对数据框进行聚合操作&#xff0c;可以按照指定的条件对数据进行分组&#xff0c;并计算每组的汇总统计量。函数如下&#xff1a; aggregate(formula,data,FUN,...) formula&#xff1a;定义聚合的公式&#xff0c;指定需要聚合的变量和分…

【精】Devops实战学习CI/CD落地方案#CI篇#

目录 先有个大概了解 基本概念 CI/CD Devops 阿里云效 devops产品 K8s jenkins docker git maven 知行合一&#xff0c;上手操作 实操记录 安装VMware 安装并配置虚拟机 安装并配置docker docker安装 修改镜像源&#xff08;关键且易出错&#xff09; CentOS…

随机森林计算指标重要性—从决策树到随机森林Python实现

文章目录 前言一、节点二、决策树2.1 案例分析——优良的水稻2.2 案例分析——家庭财富水平 三、随机森林三、Python代码实现3.1 关键问题3.1.1 节点的表示3.1.2 决策树的表示** 根节点划分左右子树的依据 **3.1.3 随机森林的构造与重要性的表示 3.2 节点类3.2 决策树类3.2.1 初…

Linux下:gcc/g++调试工具gdb

gdb 程序的发布方式有两种&#xff0c;debug模式和release模式 Linux gcc/g出来的二进制程序&#xff0c;默认是release模式 gdb mybin debug和release debug debug模式下生成的可执行程序会添加调试信息&#xff0c;所以生成的可执行程序会较大 在使用gcc/g进行编译的时…