C++ new/delete的使用

news2024/11/16 18:05:11
1.虚拟地址空间

可执行程序(进程)的虚拟地址空间:
在这里插入图片描述
内核:操作系统
栈区:函数的形参,非静态的局部变量,函数现场保护数据等等,栈是向下增长的,栈顶是低地址,栈底是高地址,存储结构为“先进后出”,栈区是一块连续的内存区域。
共享库的内存映射区域:用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存,做进程间通信。
堆区:用于程序运行时动态内存分配,堆是向上增长的,堆内存的特点是“先进先出,后进后出”,堆区是不连续的内存区域。
数据段:存储全局数据和静态数据,分为.bss和.data。
代码段:可执行的程序(机器指令)和常量数据。

2.new

new就是告诉计算机开辟一段新的空间,new开辟的空间在堆(Heap)上。new和一般的声明不同,一般声明的变量(函数内)在存放在栈上,new 负责在 堆区heap 中找到一个足以满足要求的内存。
new在堆区上创建一个对象的时候,它实际做了三件事:(1)动态分配内存空间;
(2)调用构造函数;
(3)返回正确的指针
若创建的是简单类型的变量,那么第二步就会被省略。
new还有另外一种变体,被称为定位new 运算符,能够指定使用具体的内存位置。可以用这个特性来设置其内存管理章程,处理需要通过特定地址进行访问的硬件或在特定位置创建对象。

3.new的基本用法

(1)对于基本数据类型new的用法如下:

#include<iostream>
using namespace std;
int main()
{
	//对于基本数据类型new的用法如下:
	int a = 5;
	int* p = new int(20);//使用new创建对象
	delete p;//new和delete必须对应使用,new创建一个对象,delete就要释放一个对象
	p = NULL;//释放之后将指针置为NULL,防止出现 失效指针
	int* p1 = new int[30];//使用new创建对象数组
	delete[]p1;//new创建一个对象数组,delete就要释放一组对象
	p1 = NULL;释放之后将指针置为NULL,防止出现 失效指针
	return 0;
}

(2)对于类类型new的用法如下:

class A
{
public:
	A(int i = 0) {}
	~A(){}
};
int main()
{
	A* p = new A(20);//使用new创建对象,把20给了i,相当于在new的时候把20直接给到了new出来的空间里面
	delete p;//new和delete必须对应使用,new创建一个对象,delete就要释放一个对象
	p = NULL;//释放之后将指针置为NULL,防止出现 失效指针
	A* p1 = new A[20];//使用new创建一个对象数组
	delete[]p1;//new和delete必须对应使用,new创建一个对象数组,delete就要释放一组对象
	p1 = NULL;//释放之后将指针置为NULL,防止出现 失效指针
	return 0;
}

对于基本数据类型:
使用new仅仅为对象在堆上分配了空间;
使用delete仅仅在使用完对象之后释放了这个对象的空间。
对于类类型:
使用new不仅仅为对象在堆上分配了空间,而且还调用了A的构造函数,生成了这个对象;
使用delete调用了析构函数,在使用完对象之后释放了这个对象的空间。

4.定位new

new的功能是:
(1)分配空间;
(2)调用构造函数。
其实C++规定new的这两个功能分开来实现:
(1)分配空间:调用函数 operate new 来实现;
(2)调用构造函数:调用 placement new 来实现。
定位new表示在已分配的内存中构造对象。
现在有三个 new 了,第一个 new 就是我们常说的 new,这个 new 调用接下来的两个 new 来实现它的功能。(我们称这个 new 为:new operator,叫做 “new 表达式”,因为operator 在 new 后面,所以叫做:new表达式,也就是关键字)

new 关键字会调用 operator new 来分配空间:这里 operator new 是一个全局的函数,写在一个文件中 。当使用 new 关键字的时候,编译器会自动找到这个函数,并且调用这个函数,这个函数的声明如下:

// 全局 operator new
void* operator new(std::size_t size) throw(std::bad_alloc)  {
	if(size == 0)
		size =1;
	void* p;
	while((p = ::malloc(size)) == 0)  {  // 采用 malloc 分配空间
		std::new_handler nh = std::get_new_handler();
		if(nh)
			nh();
		else
			throw std::bad_alloc();
	}
	return p;
}
// 对应的全局 operator delete 采用 free 释放空间
void operator delete(void* ptr)  {
	if (ptr)
		::free(ptr);  // 采用 free 释放空间
}

这个 operator new 函数称为 全局 operator new。(这里称为全局主要是因为:每个类还可以重载自己的 operator new() 函数)。
operator new() 函数具体使用如下:

int main()
{
	int n = 10;
	int* p1 = (int*)malloc(sizeof(int));
	int* p2 = (int*)::operator new(sizeof(int) * n);

	new(p1)int(20);
	new(p2)int[] {1, 2, 3, 4, 5, 6, 7, 8, 9};

	free(p1);
		::operator delete (p2);

	return 0;
}

operator new就是简单的分配内存

5.内存管理的基本要求

如果只考虑分配和释放,内存管理基本要求是 “不重不漏” :既不重复 delete,也不漏掉 delete。也就是我们常说的 new/delete 要配对,“配对” 不仅是个数相等,还隐含了 new 和 delete 的调用本身要匹配,不要“东家借的西家还”。例如:
(1)用系统默认的 malloc() 分配的内存要交给系统默认的 free() 去释放;
(2)用系统默认的 new 表达式创建的对象要交给系统默认的 delete 表达式去析构并释放;
(3)用系统默认的 new[] 表达式创建的对象要交给系统默认的 delete[] 表达式去析构并释放;
(4)用系统默认的 ::operator new() 分配的内存要交给系统默认的 ::operator delete() 去释放;
(5)用 placement new 创建的对象要用 placement delete 去析构(其实就是直接调用析构函数);
从某个内存池 A 分配的内存要还给这个内存池;

6.对于内置类型new/delete/malloc/free可以混用

new/delete和malloc/free的区别:
(1)new/delete 是C++中的运算符。malloc/free 是函数
(2)malloc 申请内存空间时,手动计算所需大小,new 只需要类型名,自动计算大小
(3)malloc 申请的内存空间不会初始化,new 可以初始化(需要调用构造函数)
(4)malloc 的返回值为 void*,接受时必须强转,new不需要
(5)malloc 申请内存空间失败时,返回的是NULL,使用时必须判空;new申请内存空间失败时会抛出异常(可以加上 nothrow),所以要有捕获异常处理程序

7.C和C++的动态内存管理
(1)C的动态内存管理
int main()
{
	int n = 10;
	int* p1 = (int*)malloc(sizeof(int)*n);
	int* p2 = (int*)calloc(n, sizeof(int));
	p1 = (int*)realloc(p1, sizeof(int)*n*2);

	free(p1);
	p1 = NULL;  // 释放之后一定要将指针置为NULL,防止出现 失效指针
	free(p2);
	p2 = NULL;
	return 0;
}

(2)C++的动态内存管理

new运算符的使用:

int main()
{
	int n = 10;
	int* p1 = new int(20);//20个未初始化int
	int* p2 = new int[n]();//n个值初始化为0的int
	int* p3 = new int[n] {1, 2, 3, 4, 5, 6, 7, 8, 9};//9个值初始化为1, 2, 3, 4, 5, 6, 7, 8, 9,n-9个值初始化位0
	cout << *p1 << endl;
	for (int i = 0; i < n; i++)
	{
		cout <<" " << p2[i];
	}
	cout<< endl;
	for (int i = 0; i < n; i++)
	{
		cout <<" "<< p3[i];
	}
	cout << endl;
	delete p1;
	delete[]p2;
	delete[]p3;
	return 0;
}

new的函数方式的使用:

int main()
{
	int n = 10;
	int* p1 = (int*)::operator new(sizeof(int));//operator new就是简单的分配内存
	//             (int*)malloc(sizeof(int));
	int* p2 = (int*)::operator new(sizeof(int) * n);//operator new就是简单的分配内存
	//             (int*)malloc(sizeof(int)*n);
	::operator delete(p1);
	::operator delete(p2);
	return 0;
}

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

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

相关文章

基于fpga_EP4CE6F17C8实现的呼吸灯

文章目录 前言实验手册&#xff08;EP4CE6F17C8&#xff09;一、实验目的二、实验原理理论原理 三、系统架构设计四、模块说明1&#xff0e;模块端口信号列表2&#xff0e;状态转移图3&#xff0e;时序图 五、仿真波形图六、引脚分配七、代码实现八、仿真代码九、板级验证效果 …

[CrackMe]damn.exe的逆向及注册机编写

1. 脱壳过程 这个crackme有2个文件 发现加了壳 先来脱壳, 使用ESP守恒, pushad后立马下硬件访问断点 F9直接运行, 立马到popad处 接着走几步就到了OEP 下面使用LordPE来转储映像, 为了防止别人修改PE中的ImageSize, 先尝试修正下ImageSize, 然后dump full即可 接着用x6…

《重构的时机和方法》——让你的代码更健壮、更易维护

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主&#x1f4d5;系列专栏&#xff1a;Java设计模式、Spring源码系列、Netty源码系列、Kafka源码系列、JUC源码…

简述IO(BIO NIO IO多路复用)

在unix网络变成中的五种IO模型: Blocking IO(阻塞IO) NoneBlocking IO (非阻塞IO) IO mulitplexing(IO多路复用) signal driven IO (信号驱动IO) asynchronous IO (异步IO) BIO BIO&#xff08;Blocking IO&#xff09;是一种阻塞IO模型&#xff0c;也是传统的IO操作模型之一…

不管如何吐槽,购买iPhone的用户依然义无反顾,苹果继续增长

市调机构IDC公布的二季度数据显示&#xff0c;苹果成为前五名之中除华为之外第二家取得增长的手机品牌&#xff0c;而其他国产手机品牌的出货量都在下滑&#xff0c;显示出国内的消费者仍然在热烈追捧iPhone。 二季度苹果在国内市场的手机出货量同比增长6%&#xff0c;虽然增速…

查看详细的退货信息!亚马逊在卖家中心推出新页面!

亚马逊欧洲站发布公告称亚马逊在卖家中心推出了一个新页面&#xff0c;为卖家提供详细的退货信息&#xff0c;以下是公告内容&#xff1a; 我们在卖家中心推出了一个新页面&#xff0c;为卖家提供详细的退货信息。 现在卖家可以查看每个退货订单&#xff0c;其中包含有关 ASI…

sky-notes-01

1、DTO类 DTO&#xff08;Data Transfer Object&#xff09;&#xff1a;数据传输对象&#xff0c;Service 或 Manager 向外传输的对象。 详见阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义 当前端提交的数据和实体类中对应的属性差别比较大时&#xff0c;建议使用…

【信号去噪和正交采样】流水线过程的一部分,用于对L波段次级雷达中接收的信号进行降噪(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

信号的学习笔记二

文章目录 信号捕捉signal信号捕捉sigaction信号集未决信号集和阻塞信号集的工作过程 ![在这里插入图片描述](https://img-blog.csdnimg.cn/b896346af6f1462089779e513a7e237b.png)信号集相关函数sigemptysetsigfillsetsigaddsetsigdelsetsigismember应用 以下函数设置内核信号集…

上传图片到腾讯云对象存储桶cos 【腾讯云对象存储桶】【cos】【el-upload】【vue3】【上传头像】【删除】

1、首先登录腾讯云官网控制台 进入对象存储页面 2、找到跨越访问CIRS设置 配置规则 点击添加规则 填写信息 3、书写代码 这里用VUE3书写 第一种用按钮出发事件形式 <template><div><input type="file" @change="handleFileChange" /&…

[NLP]LLM高效微调(PEFT)--LoRA

LoRA 背景 神经网络包含很多全连接层&#xff0c;其借助于矩阵乘法得以实现&#xff0c;然而&#xff0c;很多全连接层的权重矩阵都是满秩的。当针对特定任务进行微调后&#xff0c;模型中权重矩阵其实具有很低的本征秩&#xff08;intrinsic rank&#xff09;&#xff0c;因…

labelme标签格式json转化成yolov8支持是数据集格式

我们用yolov8做实例分割时&#xff0c;需要制作标签&#xff0c;如果用labelme做&#xff0c;不能直接用模型训练&#xff0c;需要利用一个脚本文件进行转换。 import base64 import random import shutil from tqdm import tqdm import math import json import os import nu…

5.2.12.读写接口实践 copy_from_user copy_to_user

5.2.12.读写接口实践 5.2.12.1、完成write和read函数 (1)copy_from_user函数的返回值定义&#xff0c;和常规有点不同。返回值如果成功复制则返回0&#xff0c;如果 不成功复制则返回尚未成功复制剩下的字节数。 copy_from_user 函数&#xff1a;static inline unsigned long _…

【业务功能篇59】Springboot + Spring Security 权限管理 【下篇】

UserDetails接口定义了以下方法&#xff1a; getAuthorities(): 返回用户被授予的权限集合。这个方法返回的是一个集合类型&#xff0c;其中每个元素都是一个GrantedAuthority对象&#xff0c;表示用户被授予的权限。getPassword(): 返回用户的密码。这个方法返回的是一个字符…

第十二章:priority_queue类

系列文章目录 文章目录 系列文章目录前言priority_queue的介绍priority_queue的使用容器适配器什么是容器适配器STL标准库中stack和queue的底层结构 总结 前言 priority_queue是容器适配器&#xff0c;底层封装了STL容器。 priority_queue的介绍 priority_queue文档介绍 优先…

路由器工作原理

路由器原理 路由概述 路由&#xff1a;跨越从源主机到目标主机的一个互联网络来转发数据包的过程。&#xff08;为数据包选择路径的过程&#xff09; 作用&#xff1a;路由器是连接不同网段的。 转发依据&#xff1a; 路由表&#xff1a;路径选择全看路由表&#xff0c;根…

大数据课程D5——hadoop的Sink

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 掌握Sink的HDFS Sink&#xff1b; ⚪ 掌握Sink的Logger Sink&#xff1b; ⚪ 掌握Sink的File Roll Sink&#xff1b; ⚪ 掌握Sink的Null Sink&#xff1b; ⚪ 掌握Si…

【前端知识】React 基础巩固(三十六)——RTK中的异步操作

React 基础巩固(三十六)——RTK中的异步操作 一、RTK中使用异步操作 引入RTK中的createAsyncThunk&#xff0c;在extraReducers中监听执行状态 import { createSlice, createAsyncThunk } from "reduxjs/toolkit"; import axios from "axios";export cons…

<MySQL> Centos 7环境安装MySQL

Centos 7环境安装MySQL 1.卸载不要的环境 停止MySQL服务 systemctl stop mariadb.service systemctl stop mysqld禁止MySQL服务开机自启 systemctl disable mysqld卸载MySQL软件包 yum remove mysql-server mysql-client删除MySQL数据目录 rm -rf /var/lib/mysql清理MySQ…

福特汽车在全球电动汽车市场的主导地位正在不断扩大

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 2023年7月27日&#xff0c;美国最大的汽车巨头之一福特汽车(F)公布了其2023年第二季度财报。 2023年7月6日&#xff0c;福特汽车宣布&#xff0c;第二季度美国市场的汽车销量已经较2023年第一季度增长了11.7%&#xff0c;令…