C++第十一节课 new和delete

news2024/9/21 0:22:47

一、new和delete操作自定义类型

        new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数(new会自动调用构造函数;delete会调用析构函数)

class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};
int main()
{
	// new/delete 和 malloc/free最大区别是 
	// new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数
	A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A(1);
	free(p1);
	delete p2;
	return 0;
}

通过调试可以发现new可以将值初始化为1;

如果是多个对象:

A* p5 = (A*)malloc(sizeof(A)*10);
A* p6 = new A[10];
free(p5);
delete[] p6;

每个元素都会调用一次构造函数和析构函数!

此时数组会调用默认构造函数将每个元素初始化为0;

如果没有默认构造函数,那么此时需要我们自己向构造函数传递数值;

分析下面的代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class A
{
public:
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};
int main()
{
	A* p5 = (A*)malloc(sizeof(A) * 10);
	A* p6 = new A[10];
	free(p5);
	delete[] p6;
	return 0;
}

上面类中只有系统提供的默认的构造函数,new初始化对象的时候调用系统提供的默认构造函数,但是这个默认构造是跟malloc一样,将数组中的元素初始化为随机值;

如果构造函数不是默认构造函数:

class A
{
public:
	A(int a)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};
int main()
{

	A* p5 = (A*)malloc(sizeof(A) * 10);
	A* p6 = new A[4]{1,2,3,4};
	A* p7 = new A[4]{ A(1),A(2),A(3),A(4) };
	free(p5);
	delete[] p6;
	return 0;
}

这里相当于隐式类型转换:1,2,3,4类型为A,1会调用构造函数(作为参数传递)变为A类型;

等价于下面A* p7!两者是等价的!(A(1),A(2),A(3),A(4)是匿名对象);

  • 如果A有默认构造,那么可以采用注释的方式,前三个根据提供的值进行初始化,最后一个根据默认构造进行初始化;
  • 如果A没有默认构造,那么必须提供准确的值进行初始化,每个元素都需要提供;

如果new对象再free,malloc再delete出产生什么结果?

对于内置类型,一般不会出现大问题;

但是对于自定义类型:

直接会引发程序崩溃!

原则:一定包匹配使用,否则可能会出现大问题!(结果是不确定的!)

二、operator newoperator delete函数 

operator new与operator delete不是一个运算符重载,而是一个全局函数!(库里面的)

free是一个宏函数,底层调用_free_dbg;

malloc如果失败,会返回空,但是面向对象语言处理失败,不喜欢用返回值,更建议用抛异常;

直到返回空然后程序结束; 

32位的进程空间总共的寄存器大小为4G(会有4G的虚拟内存 / 堆的总大小不会超过2G);

使用new申请过于大的空间会直接报异常:

可以使用下面的形式捕获异常,catch会捕捉失败的地方(具体语法后面讲):

报异常后会将之前开辟的内存直接释放;

因此,虽然new的功能是:开空间 + 构造函数,开空间部分如果直接调用malloc,那么开辟失败会返回空指针,不会报异常,C++希望的是报异常;

因此引入:operator new,实际上是对malloc的封装,如果失败了会报异常!

因此,实际上new开空间的功能是调用operator new,而operator new实际上是调用malloc!

delete释放空间的功能实际上是调用operator delete函数,而operator delete函数底层是通过封装free函数来实现的!

通过观察可以发现:new实际上就是调用operator new和构造函数!(先开空间再调用构造函数)

同理:delete实际上就是调用operator delete和析构函数(先调用析构函数清理资源,再释放空间;)

三、定位new表达式(placement-new)

分析下面场景:如果我们需要申请一个堆上的栈对象!

调用new的时候,首先,创建的指针变量位于栈区,然后调用operator new在堆上创建对应的成员变量空间!然后会调用构造函数在堆区创建数组空间(堆上的_array指向arr)!

同理:这个过程中,会先调用析构函数清理stack对象指向的资源arr(析构函数释放由于构造函数开辟的资源),operator delete调用free将开辟的成员变量释放!

科普:定位new的用途

如果需要频繁的申请和释放内存(直接在堆上找到合适的空间是一个比较麻烦的事),那么我们可以构造内存池,每次从这个池子中去申请(直接在内存池中申请会比直接在堆上申请快一点);

new是直接在堆上找到合适的内存进行初始化,而我们在内存池中找到的空间没办法进行初始化!

这时候我们可以采用定位new进行初始化!

STL中的链表源码实际上就用到了定位new!

  • 这里的construct就是调用定位new;
  • destory就是显示调用析构函数;
  • 并且代码量少的函数直接设置为内联;

总结:

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

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

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

四、内存泄漏

cout打印int*是按照指针类型进行打印的,但是cout打印char*会将其识别为一个字符串!

对于上面的代码,申请1G的内存,打印的p1会是乱码;

cout将char*识别为一个字符串,打印字符串遇到 \0 才停止,但是上面申请的内存没有进行初始化,因此会一直找 \0 ,且没有初始化的空间为随机值。

因此,我们将其初始化就不会遇到上面的错误!

如果我们想要按照地址打印char*类型怎么办?

方法一:使用printf进行打印(%p);

方法二:使用cout将其转化为(void*)进行打印!

进程结束的时候,操作系统会自动的将进程给回收了;

因此,平时我们运行的时候,就算不手动释放,操作系统会帮我们自动释放;

总结:

  • 普通程序,内存泄漏影响不大,进程正常结束会释放资源;
  • 长期运行的程序(服务器),内存泄漏危害很大,例如 --- 游戏服务,电商服务......

        什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
        内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

五、模板引入

模板分为:函数模板 + 类模板

引入关键字:template(模板)typename可以缩写为T,其中T被称为模板参数;

函数模板

模板参数定义的是类型;

template<typename T>
void Swap(T& left, T& right)
{
	T tmp = left;
	left = right;
	rifht = tmp;
}

int main()
{
	int a = 0, b = 1;
	double c = 1.1, d = 2.2;
	Swap(a, b);
	Swap(c, d);
	return 0;
}

问题:对于上面的代码,两次调用的Swap是否是同一个函数?

答案:不是同一个函数!

根据汇编代码可以分析:调用的不是同一个函数,调用根据模板生成的具体的函数(这个过程也叫做模板的实例化)

编译器根据函数模板生成对应具体的函数!

注意点:C++内置自己提供了swap函数,不需要我们自己实现!

底部也是根据模板实现的!

这里的swap可以交换内置类型和自定义类型!

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

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

相关文章

systemd学习

传统init进程启动流程 kernel内核代码init/main.c&#xff0c;内核启动init进程过程&#xff1a; init进程是由内核启动的第一个&#xff08;也是唯一的一个&#xff09;用户进程&#xff08;进程id为1&#xff09;&#xff0c;它根据配置文件决定启动哪些程序&#xff0c;ini…

mybatisplus的多记录操作 批量删除和批量查询

1.批量查询 通过in查询 Testpublic void testBatchSelectByIds(){List<Integer> ids Arrays.asList(5,7);List<User> users userMapper.selectBatchIds(ids);log.info(users);} 2.批量删除 Testpublic void testBatchDelete(){List<Integer> ids Arrays…

LLM - 理解 多模态大语言模型(MLLM) 的 指令微调(Instruction-Tuning) 与相关技术 (四)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142237871 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 完备(F…

Java知识点小结3:内存回收

文章目录 对象引用强引用软引用&#xff08;SoftReference&#xff09;弱引用&#xff08;WeakReference&#xff09;考一考 虚引用&#xff08;PhantomReference&#xff09;总结 垃圾回收新生代老年代永生代 内存管理小技巧尽量使用直接量使用StringBuilder和StringBuffer进行…

Vue学习记录之六(组件实战及BEM框架了解)

一、BEM BEM是一种前端开发中常用的命名约定&#xff0c;主要用于CSS和HTML的结构化和模块化。BEM是Block、Element、Modifier的缩写。 Block&#xff08;块&#xff09;&#xff1a;独立的功能性页面组件&#xff0c;可以是一个简单的按钮&#xff0c;一个复杂的导航条&…

A Simple Encoder-Decoder for Open-Vocabulary Semantic Segmentation

FAM: Feature Aggregation Module&#xff0c;Circle with R represents removing feature maps of non-selected categories 辅助信息 权重有1.3G&#xff0c;不建议复现

neo4j关系的创建删除 图的删除

关系的创建和删除 关系创建 CREATE (:Person {name:"jack"})-[:LOVE]->(:Person {name:"Rose"})已有这个关系时&#xff0c;merge不起效果 MERGE (:Person {name:"Jack" })-[:LOVE]->(:Person {name:"Rose"})关系兼顾节点和关…

功耗中30分钟下载场景对平均电流标准的影响评估

下载场景的测试数据: 测试结论:相同场景下,有应用下载安装跟没应用下载安装,平均电流相差90-140mA左右 查看数据:下载场景的平均增量电流 (227+279) / 2 - 136 = 117 mA 理论的量化数据影响 根据当前的测试数据:静置待机平均电流 136 mA,下载场景平均电流增量 117mA, …

相亲交易系统源码详解与开发指南

随着互联网技术的发展&#xff0c;越来越多的传统行业开始寻求线上转型&#xff0c;其中就包括婚恋服务。传统的相亲方式已经不能满足现代人快节奏的生活需求&#xff0c;因此&#xff0c;开发一款基于Web的相亲交易系统显得尤为重要开发者h17711347205。本文将详细介绍如何使用…

电气自动化入门05:三相异步电动机的正反转点动控制电路

视频链接&#xff1a;3.2 电工知识&#xff1a;三相异步电动机的正反转点动控制电路_1_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1PJ41117PW?p6&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 1.断路器及其选型 1.1断路器定义、分类、表示符号 1.2.断路器功能、…

Vision Transform—用于大规模图像分类的Transformers架构

VIT — 用于大规模图像识别的 Transformer 论文题目&#xff1a;AN IMAGE IS WORTH 16X16 WORDS:TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE。 官方代码&#xff1a;https://github.com/google-research/vision_transformer 引言与概述 Vision Transformer&#xff08;ViT&…

虚拟机vaware中cpu设置跑满大核

首先&#xff0c;大核速度快&#xff0c;并且在资源紧张时大核优先&#xff0c;小核甚至是闲着围观大核跑满。其次&#xff0c;遇到经常切换操作虚拟机和win11的使用场景&#xff0c;切换核心本身也会造成一点卡顿&#xff0c;降低虚拟机里操作流畅度。另外&#xff0c;13代在你…

【linux】4张卡,坏了1张,怎么办?

先禁用这张卡 grub 禁用&#xff0c;防止加载驱动 禁用这张卡的 PCI # 禁用 PCI 设备 0000:b1:00.0 (NVIDIA GPU) ACTION"add", SUBSYSTEM"pci", ATTR{vendor}"0x10de", KERNELS"0000:b1:00.0", RUN"/bin/sh -c echo 0000:b1:00…

vue part 10

vue-resource 在vue1.0时代讲的比较多&#xff0c;是vue.插件库&#xff0c; import vueResource from vue-resourceVue.use(vueResource) 在vc和vm中会多出如下F12代码即&#xff0c;$http:() 他的用法和返回值和axios一模一样&#xff0c;但是不常维护了 插槽 默认插槽 …

11年计算机考研408-数据结构

设执行了k次。 解析&#xff1a; d要第一个出&#xff0c;那么abc先入栈&#xff0c;d入栈然后再出栈&#xff0c;这前面是一个固定的流程&#xff0c;后面就很灵活了&#xff0c;可以ecba&#xff0c;ceba&#xff0c;cbea&#xff0c;cbae。 答案是4个序列。 解析&#xff1a…

解决redis缓存击穿问题之布隆过滤器

布隆过滤器 1. 什么是布隆过滤器 布隆过滤器&#xff08;Bloom Filter&#xff09;是一个空间效率很高的数据结构&#xff0c;用于判断一个元素是否在一个集合中。布隆过滤器的核心思想是利用位数组和一系列随机映射函数&#xff08;哈希函数&#xff09;来快速判断某个元素是…

基于SpringBoot+Vue+MySQL的网上租赁系统

系统展示 用户前台界面 管理员后台界面 系统背景 在当前共享经济蓬勃发展的背景下&#xff0c;网上租赁系统作为连接租赁双方的重要平台&#xff0c;正逐步改变着人们的消费观念和生活方式。通过构建一个基于SpringBoot、Vue.js与MySQL的网上租赁系统&#xff0c;我们旨在为用户…

LangChain 和 Elasticsearch 加速构建 AI 检索代理

作者&#xff1a;来自 Elastic Joe McElroy, Aditya Tripathi, Serena Chou Elastic 和 LangChain 很高兴地宣布发布新的 LangGraph 检索代理模板&#xff0c;旨在简化需要代理使用 Elasticsearch 进行代理检索的生成式人工智能 (GenAI) 代理应用程序的开发。此模板预先配置为使…

基于机器学习的癌症数据分析与预测系统实现,有三种算法,bootstrap前端+flask

研究背景 癌症作为全球范围内最主要的死亡原因之一&#xff0c;已成为当代医学研究和公共健康的重大挑战。据世界卫生组织&#xff08;WHO&#xff09;的统计&#xff0c;癌症每年导致全球数百万人的死亡。随着人口老龄化、环境污染和生活方式的改变&#xff0c;癌症的发病率逐…

Pytorch学习---基于经典网络架构ResNet训练花卉图像分类模型

基于经典网络架构训练图像分类模型 导包 import copy import json import time import torch from torch import nn import torch.optim as optim import torchvision import os from torchvision import transforms, models, datasets import numpy as np import matplotlib.…