【020】C++的动态内存申请new和delete

news2024/9/25 1:23:40

C++的动态内存申请new和delete

  • 引言
  • 一、动态分配内存的概述
  • 二、静态分配和动态分配
  • 三、new和delete
    • 3.1、new和delete操作基本类型空间
    • 3.2、new和delete操作数组空间
  • 四、new和delete的重载
  • 五、动态分配内存的优缺点
  • 总结

引言


💡 作者简介:专注于C/C++高性能程序设计和开发,理论与代码实践结合,让世界没有难学的技术。包括C/C++、Linux、MySQL、Redis、TCP/IP、协程、网络编程等。
👉
🎖️ CSDN实力新星,社区专家博主
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【019】C++的指针与函数

一、动态分配内存的概述

C++中的动态内存分配是在程序运行时根据需要进行内存空间的分配和释放,与静态内存分配相比,具有更大的灵活性和适应性。动态内存分配可以通过newdelete或者malloc()free()等函数实现。

动态内存分配通常用于以下情况:

  • 在程序运行时无法确定所需的内存大小。
  • 需要在多个函数之间共享数据,并且数据可能被频繁地创建和销毁。
  • 静态数组无法满足需求,例如需要支持可变长度数组。

如果在动态分配内存后忘记了释放它,则会导致内存泄漏。为避免内存泄漏,可以使用智能指针或手动管理内存的方式来释放动态分配的内存。

二、静态分配和动态分配

(1)静态分配:

  • 在程序编译或运行过程中,按事先规定大小分配内存空间的分配方式。
  • 必须事先知道所需空间的大小。
  • 分配在栈区或全局变量区,一般以数组的形式。

(2)动态分配:

  • 在程序运行过程中,根据需要大小自由分配所需空间。
  • 按需分配。
  • 分配在堆区,一般使用特定的关键字进行分配。

(3)堆和栈的区别:

  • 分配方式:堆是动态分配,栈是静态分配。
  • 内存大小:堆内存大小没有限制(除了计算机硬件限制),而栈的大小受到编译器、操作系统等因素的影响。
  • 空间分配:堆空间由程序员手动申请、释放;栈空间由编译器自动分配、回收。
  • 访问速度:由于栈采用先进先出原则,访问速度比堆要快。
  • 管理方式:堆内存由程序员手动管理,容易出错;栈内存由编译器自动管理,减轻了程序员的负担。

三、new和delete

在 C++ 中,动态内存的申请和释放需要使用关键字 newdelete

new 是一个操作符,可以用来在堆上分配一段内存,并返回该内存块的地址。它的语法为:

new 数据类型;

例如:

int* p = new int; // 在堆上分配一个 int 类型的空间
double* q = new double; // 在堆上分配一个 double 类型的空间

使用了 new 操作符在堆上分别申请了一个 int 类型和一个 double 类型的空间,并将其地址赋值给指针变量 pq

如果要同时初始化所申请的内存块,可以使用如下形式:

数据类型* 指针名 = new 数据类型(初值);

例如:

int* p = new int(10); // 在堆上分配一个 int 类型的空间,并初始化为 10
char* q = new char('A'); // 在堆上分配一个 char 类型的空间,并初始化为 'A'

使用 new 分配了内存后,在不再需要这些内存时应该手动释放。释放所申请的内存可以使用关键字 delete。它有两种用法:一种是只删除单个对象的内存块,另一种是删除数组的内存块。

  • 删除单个对象。要删除单个对象,在 delete 后面加上指向该对象的指针即可:
delete 指针名;

例如:

int* p = new int(10); // 在堆上分配一个 int 类型的空间,并初始化为 10
delete p; // 释放申请的空间

注意:使用完 new 分配的内存后,一定要记得使用 delete 将其释放掉,否则会造成内存泄漏。

  • 删除数组。如果使用了带有方括号 [] 的 new 来分配数组,则需要使用带有方括号 [] 的 delete 来释放所申请的内存。语法如下:
delete[] 数组指针;

例如:

int* p = new int[5]; // 在堆上分配一个长度为 5 的 int 数组
delete[] p; // 释放申请的空间

注意:在使用带有方括号 [] 的 new 分配数组时,必须使用带有方括号 [] 的 delete 进行释放,否则会导致未定义行为。

示例:

#include <iostream>
using namespace std;

int main() {
    int* p1 = new int;
    *p1 = 10;
    cout << "p1: " << *p1 << endl;

    double* p2 = new double(3.14);
    cout << "p2: " << *p2 << endl;

    int* arr = new int[5];
    for (int i = 0; i < 5; i++) {
        arr[i] = i + 1;
        cout << "arr[" << i << "]: " << arr[i] << endl;
    }
    delete[] arr;

    delete p1;
    delete p2;

    return 0;
}

输出结果:

p1: 10
p2: 3.14
arr[0]: 1
arr[1]: 2
arr[2]: 3
arr[3]: 4
arr[4]: 5

3.1、new和delete操作基本类型空间

new负责申请空间,delete负责释放空间。

#include <iostream>
using namespace std;
int main()
{
	int *x=new int;//从堆区申请int类型大小的空间
	
	x=100;
	
	cout<<"*x = "<<*x<<endl;
	
	int *x2=new int(1000);//从堆区申请int类型大小的空间,并初始化
	cout<<"*x2 = "<<*x2<<endl;
	
	delete x2;//释放空间
	delete x;//释放空间
	return 0;
}

3.2、new和delete操作数组空间

new与[]结合表示申请数组空间,delete释放的时候也需要[]。

#include <iostream>
using namespace std;
int main()
{
	int *arr = new int[5]{ 1,2,3,4,5 };
	for (int i = 0; i < 5; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	delete[] arr;

	return 0;
}

输出:

1 2 3 4 5

四、new和delete的重载

C++ 中可以通过重载 newdelete 操作符来实现自定义的内存管理。重载后的操作符可以用于在不同情况下分配和释放内存。

  1. 重载 new 操作符可以使用 operator new 函数来重载 new 操作符。它是一个静态成员函数,其原型如下:
void* operator new (size_t size);

其中,参数 size 表示要申请的内存块大小,返回值为指向申请到的内存块的指针。以下是一个简单的例子:

#include <iostream>
using namespace std;

class MyClass {
public:
    void* operator new (size_t size) {
        cout << "Customized allocation of " << size << " bytes memory." << endl;
        return malloc(size);
    }
};

int main() {
    MyClass* p = new MyClass();
    delete p;
    return 0;
}

输出结果:

Customized allocation of 1 bytes memory.

上述代码中,定义了一个名为 MyClass 的类,并在其中重载了 new 操作符。在这个例子中,没有真正地改变分配内存的方式,而是只是增加了一些输出信息以便观察调用情况。

  1. 重载 delete 操作符也可以使用 operator delete 函数来重载 delete 操作符。它也是一个静态成员函数,其原型如下:
void operator delete (void* ptr);

其中,参数 ptr 表示要释放的内存块地址。

简单的例子:

#include <iostream>
using namespace std;

class MyClass {
public:
    void* operator new (size_t size) {
        cout << "Customized allocation of " << size << " bytes memory." << endl;
        return malloc(size);
    }

    void operator delete (void* ptr) {
        cout << "Customized deallocation." << endl;
        free(ptr);
    }
};

int main() {
    MyClass* p = new MyClass();
    delete p;
    return 0;
}

输出结果:

Customized allocation of 1 bytes memory.
Customized deallocation.

上述代码中,不仅重载了 new 操作符,还重载了 delete 操作符。在这个例子中,通过使用 free() 函数来释放内存。

需要注意的是,在重载 delete 操作符时,必须与重载 new 操作符配对使用。也就是说,如果想自定义分配方式,则需要同时自定义释放方式。

上述是在类中重载,也可以在非类中重载newdelete操作符实现自定义的内存分配和释放方式。例如:

void* operator new(size_t size) {
    void* p = malloc(size);
    if(!p) throw std::bad_alloc();
    return p;
}

void operator delete(void* p) noexcept {
    free(p);
}

以上代码实现了一个自定义的newdelete操作符,其中使用了标准库中的异常类std::bad_alloc()来处理内存申请失败的情况,并使用了C语言中的malloc()free()函数来进行内存分配和释放。

需要注意的是,在重载操作符时需要保证与标准库中的操作符具有相同的语义,否则可能会导致意外行为或程序崩溃。

五、动态分配内存的优缺点

动态分配内存的优点:

  1. 灵活性:动态分配内存允许程序根据需要在运行时分配和释放内存,从而可以适应不同的数据量和操作需求。

  2. 节省空间:动态分配内存只会占用实际需要的空间,避免了静态分配过多空间造成的浪费。

  3. 提高效率:合理利用动态内存分配可以提高程序的效率,尤其是对于大型数据结构或需要多次重复调用某个函数的情况。

  4. 可扩展性:由于动态内存分配可以根据需求增加或减少内存空间,因此程序具有很好的可扩展性。

动态分配内存的缺点:

  1. 内存泄漏:如果不正确地使用和管理动态分配的内存,就可能导致内存泄漏问题,这会严重影响程序运行效率和稳定性。

  2. 复杂性:相比静态内存分配,在动态内存分配中需要进行更多复杂的操作,如申请、释放、回收等。同时也需要考虑到指针、数组等相关问题。

  3. 代码容易出错:由于涉及到指针操作和较为复杂的编程技巧,因此代码容易出现错误,增加了程序的调试难度。

  4. 程序安全性:由于动态内存分配可以被黑客用来进行缓冲区溢出等攻击,因此需要谨慎使用,并做好相应的安全措施。

总结

C++中的动态内存分配是在程序运行时根据需要进行内存空间的分配和释放,与静态内存分配相比,具有更大的灵活性和适应性。动态内存分配可以通过newdelete或者malloc()free()等函数实现。

  1. newdelete

使用new关键字可以在堆上分配指定类型大小的内存空间,并返回指向该空间起始位置的指针。例如:

int *p = new int; // 分配一个int类型大小的空间
*p = 10;          // 对该空间赋值
delete p;         // 释放该空间

使用new[]关键字可以在堆上分配指定数量、类型大小相同的连续内存空间,并返回指向该空间起始位置的指针。例如:

int size = 10;
int *arr = new int[size]; // 分配一个包含10个int类型元素的数组
for(int i = 0; i < size; i++) {
    arr[i] = i;
}
delete[] arr; // 释放该数组

需要注意的是,使用newdelete时需要保证分配和释放的内存大小和类型一致,否则会导致内存泄漏或程序崩溃。

  1. 内存泄漏。如果在动态分配内存后忘记了释放它,则会导致内存泄漏。为避免内存泄漏,可以使用智能指针或手动管理内存的方式来释放动态分配的内存。

  2. 其他注意事项:

  • 动态分配出来的对象必须通过调用其析构函数来释放资源。
  • 如果动态分配出来的对象要被当作参数传递给函数,则最好将其封装成智能指针,以确保资源能够正确地被释放。
  • 动态分配时应该根据实际需要进行内存分配,避免过度分配导致资源浪费或不足导致程序崩溃。

在这里插入图片描述

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

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

相关文章

【算法系列 | 2】深入解析排序算法之插入排序

序言 你只管努力&#xff0c;其他交给时间&#xff0c;时间会证明一切。 文章标记颜色说明&#xff1a; 黄色&#xff1a;重要标题红色&#xff1a;用来标记结论绿色&#xff1a;用来标记一级论点蓝色&#xff1a;用来标记二级论点 决定开一个算法专栏&#xff0c;希望能帮助大…

看这篇文章能让你健康多活若干年

这个世界值得你多活几十年&#xff0c;即便你对现在的生活不满意&#xff0c;你也会对几十年后的生活倾慕不已。 毕竟&#xff1a; 到2029年&#xff0c;区块链就出来第二十年了&#xff0c;Web3会让我们生活得更容易。 到2042年&#xff0c;chatGPT就出来第二十年了&#xff0…

SpringCloudAlibaba

Spring Cloud Alibaba 是 Spring Cloud 的一个子项目&#xff0c;它是由阿里巴巴开发的一套微服务解决方案&#xff0c;旨在为微服务架构提供一站式解决方案&#xff0c;包括服务注册与发现、配置中心、消息总线、负载均衡、熔断器、限流器、分布式事务等组件。 Spring Cloud A…

阿里、字节大佬共创的Netty核心原理手册,必须是全网No.1

讲到这里&#xff0c;你可能要问了&#xff1a;如果我的工作中涉及网络编程的内容并不多&#xff0c;那我是否还有必要花精力学习 Netty 呢&#xff1f;其实在互联网大厂&#xff08;阿里、腾讯、美团等&#xff09;的中高级 Java 开发面试中&#xff0c;经常会问到涉及到 Nett…

将一个数组分为多个数组按其元素总数尽量均分的numpy.array_split()方法

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将一个数组s分为多个数组 按s中元素总数尽量均分 numpy.array_split() [太阳]选择题 关于以下代码说法错误的一项是? import numpy as np a np.array([1,2,3,4]) print("【显示】a &quo…

突发!ChatGPT之父警告AI可能灭绝人类,350名AI权威签署联名公开信

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ni7WOmZz-1685770686028)(C:\Users\lenovo\AppData\Local\Temp\ksohtml3116\wps1.jpg)] 就在刚刚&#xff0c;AI 领域传出一封重要的公开信。 包括 「ChatGPT 之父」Sam Altman 在内 350 位 AI 权威都…

【历史上的今天】6 月 5 日:揭幕计算机历史的一次聚会;公钥密码学先驱诞生;函数语言设计先驱出生

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 6 月 5 日&#xff0c;世界环境日。1972 年 6 月 5 日至 16 日&#xff0c;联合国人类环境会议在斯德哥尔摩举行&#xff0c;会上发表了《人类环境言》&#x…

tdesign的白天黑夜模式实现原理

以tdesign为例 我们看下源码 可以看到,tdesign是借助于:root选择器,并结合属性选择器来设置的,当html标签存在一个名叫theme-mode属性的时候,如果值为dark就使用白天的主题,否则就使用黑天的主题 我们切换下颜色,更改html当中的属性,可以看到下图的区别 <!DOCTYPE html&g…

​细说websocket -Node篇​

一、WebSocket 协议 1. 概述 websocket协议允许不受信用的客户端代码在可控的网络环境中控制远程主机。该协议包含一个握手和一个基本消息分帧、分层通过TCP。简单点说&#xff0c;通过握手应答之后&#xff0c;建立安全的信息管道&#xff0c;这种方式明显优于前文所说的基于…

中国汽车品牌出海简直“泰裤辣”!

世界上有五种辣&#xff1a;微辣、中辣、特辣、变态辣&#xff0c;还有一种叫“泰裤辣”&#xff01;随着中国汽车品牌出海的步伐加快&#xff0c;泰国市场成为了一个备受关注的目标。无论是泰国对汽车产业的激励政策&#xff0c;还是泰国当地对促进汽车消费的力度&#xff0c;…

三星不愿成为炮灰,加速抢占美光的市场,美国的愿望落空

在美光被中国实施安全审查后&#xff0c;美国曾要求韩国芯片不要趁机扩大销售&#xff0c;抢占美光留下的市场人&#xff0c;然而由于全球芯片行业的衰退&#xff0c;三星等韩国企业担忧成为炮灰而加速抢占美光的市场。 一、韩国芯片不好过 三星等韩国芯片企业如此做&#xff0…

yolov5s融合ECA、CA、Transformer等组件开发构建海洋场景下远红外目标检测模型,并进行实验对比分析

海洋海面远红外场景下的目标检测在我之前的文章中已经有过相关的实践了&#xff0c;感兴趣的话可以自行移步阅读即可。 《红外海洋目标检测实践&#xff0c;基于目标检测模型识别红外海洋目标》 《基于YOLO开发构建红外场景下无人机航拍车辆实例分割检测识别分析系统》 《红…

CAD软件外包开发的技术难点

CAD软件的开发具有一定的复杂性和挑战性&#xff0c;需要复杂的数学和几何计算&#xff0c;同时需要兼顾高性能&#xff0c;这对软件开发者有比较高的要求。今天和大家分享这方面的知识&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发…

Centos升级docker后启动容器报错“unknown or invalid runtime name”

前言 操作系统为centosdocker原来的版本为1.31.1&#xff0c;升级后为20结尾有升级docker的教程听说图片能凑字数&#xff0c;就截图贴了 插播一个问题记录 加入后面出现无法强制删除镜像文件时&#xff0c;或者报错&#xff08;无法创建容器&#xff09; 按照如下解决 1. 报…

多语言跨境商城源码系统选择定制开发|多语言电商源码

多语言跨境商城源码选择 欢迎名片沟通 多语言跨境商城源码系统应当具有符合自身需求的语言和环境&#xff0c;具体应有&#xff1a;多语言支持、界面设计、支付方式、物流配送、安全性、性能和稳定性、可扩展性等等。具体如下&#xff1a; 多语言支持——具备语言切换…

13.生命周期函数

小程序中的生命周期函数分为两种 应用生命周期函数&#xff1a;整个应用的生命周期函数页面生命后期函数 目录 1 应用生命周期函数 1.1 初始化时 onLanch 1.2 隐藏小程序时 onHide 1.3 显示小程序时 onShow 2 页面生命周期函数 2.1 初始化时 onLoad 2.2 页面显…

C语言写网络爬虫总体思路

使用C语言编写爬虫可以实现网络数据的快速获取和处理&#xff0c;适用于需要高效处理海量数据的场景。与其他编程语言相比&#xff0c;C语言具有较高的性能和灵活性&#xff0c;可以进行底层操作和内存管理&#xff0c;适合处理较复杂的网络请求和数据处理任务。 但是&#xf…

OpenAI网站3月份独立访问量突破8.47亿,增长54%;10分钟搭建自己可免费商用的ChatGPT环境

&#x1f989; AI新闻 &#x1f680; OpenAI网站3月份独立访问量突破8.47亿&#xff0c;增长54% 摘要&#xff1a;据营销机构VezaDigital的调查数据显示&#xff0c;今年3月份共有8.47亿用户访问了OpenAI的网站&#xff0c;比2月份增长了54%。OpenAI是爆火聊天机器人ChatGPT的…

苹果手机备份软件iMazing2023免费版下载

Mazing 则是完全符合用户的使用习惯&#xff0c;可以非常方便地选择一个文件夹即可导入&#xff0c;或者直接像文件管理器那样&#xff0c;用鼠标拖放文件即可完成音乐的传输&#xff0c;简单至极&#xff01;这点 iTunes 是做不到的。iMazing 可以帮助你轻松快速在本地备份自己…

数据中心低压配电系统能耗分析与PUE计算

本篇内容是同为科技&#xff08;TOWE&#xff09;整编的现代化数据中心能耗及PUE的基本概念解读与分析&#xff0c;PUE作为数据中心机房建设节能技术衡量工具&#xff0c;正确理解PUE的涵义&#xff0c;采取针对措施降低PUE值&#xff0c;寻找节能高效与成本合理的平衡点&#…