C++动态分配内存知识点!

个人主页:PingdiGuo_guo

收录专栏:C++干货专栏

大家好呀,又是分享干货的时间,今天我们来学习一下动态分配内存。

文章目录

1.动态分配内存的思想

2.动态分配内存的概念

2.1内存分配函数

2.2动态内存的申请和释放

2.3内存碎片问题

3.动态分配内存的作用

3.1 灵活分配内存空间

3.2 提高内存利用率

3.3 动态数据结构的实现

3.4 避免内存溢出和内存泄漏

3.5 提高程序的性能

3.6 总结

4.动态分配内存的实现

4.1 步骤

4.1.1 确定需要分配的内存大小

4.1.2 使用new操作符分配内存

4.1.3 检查分配是否成功

4.1.4 使用分配的内存

4.2 代码示例

5.动态分配内存的分类及代码

5.1 动态分配单个对象的内存

5.1.1 介绍

5.1.2 代码示例

5.2 动态分配对象数组的内存

5.2.1 介绍

5.2.2 代码示例

5.3 注意事项

6.动态分配内存的练习

6.1 题目描述

6.2 知识点

6.3 步骤

6.3.1 初始化

6.3.2 输入数组大小

6.3.3 分配内存

6.3.4 输入字符串内容

6.3.5 显示字符串内容

6.3.6 用户选择

6.3.7 释放内存

6.3.8 结束程序

6.4 代码

7.总结


1.动态分配内存的思想

动态分配内存是指在程序运行时根据需要动态地分配内存空间。这相对于静态分配内存来说,静态分配内存是在编译时固定地分配内存空间,而动态分配内存可以在程序运行期间根据实际需求进行内存的申请和释放,以提高内存的利用率和灵活性。

2.动态分配内存的概念

动态分配内存的概念包括以下几个方面:

2.1内存分配函数

动态分配内存需要使用内存分配函数,如C语言中的malloc()、calloc()、realloc()等,这些函数可以根据需要在运行时动态地分配一块连续的内存空间。

2.2动态内存的申请和释放

使用内存分配函数可以申请一块指定大小的内存空间,申请的内存空间可以在程序运行期间使用。使用完毕后,可以使用释放函数将内存空间释放,以便其他程序继续使用。

2.3内存碎片问题

动态分配内存可能会导致内存碎片问题。当频繁地进行内存分配和释放操作时,可能会在内存中留下一些未被使用的小块内存,这些小块内存无法被再次利用,导致内存的浪费。为了解决内存碎片问题,可以使用内存管理算法来进行内存的分配和释放操作。

3.动态分配内存的作用

动态分配内存在计算机编程中有很多重要的作用,包括:

3.1 灵活分配内存空间

动态分配内存可以根据程序的实际需求,在运行时动态地申请适当大小的内存空间。这使得程序可以根据具体情况来分配所需的内存,提高了程序的灵活性和适应性。

3.2 提高内存利用率

动态分配内存可以避免静态分配内存的固定大小限制,可以根据实际需要进行灵活的内存分配。这样可以更有效地利用内存资源,避免了内存的浪费。

3.3 动态数据结构的实现

动态分配内存是实现动态数据结构(如链表、树等)的基础。动态数据结构的大小可能在程序运行过程中变化,需要动态地为其分配和释放内存空间。

3.4 避免内存溢出和内存泄漏

动态分配内存可以避免程序因为内存空间不足而导致的内存溢出错误。同时,使用动态分配内存还可以确保内存的正确释放,避免造成内存泄漏问题。

3.5 提高程序的性能

动态分配内存可以减少内存碎片的问题,提高内存的利用效率。同时,动态分配内存也可以减少静态分配内存的开销,提高程序的性能。

3.6 总结

总之,动态分配内存在计算机编程中具有重要的作用,它可以提供灵活的内存分配方式,提高内存的利用率,支持动态数据结构的实现,避免内存溢出和内存泄漏问题,同时提高程序的性能。

4.动态分配内存的实现

在C++中,动态内存分配通常使用new和delete操作符来完成。下面我将分步骤和代码两部分来介绍如何进行动态内存分配。



4.1 步骤

4.1.1 确定需要分配的内存大小

首先,你需要确定要分配多少内存。这通常取决于你要存储的数据类型以及你要存储多少这样的数据。


4.1.2 使用new操作符分配内存

使用new操作符来分配内存。例如,如果你要分配一个整数数组,你可以使用new int[size],其中size是你想要的数组大小。


4.1.3 检查分配是否成功

new操作符在无法分配所需内存时会返回nullptr。因此,你应该检查返回的指针是否为nullptr,以确保内存已成功分配。


4.1.4 使用分配的内存

一旦内存成功分配,你就可以开始使用它。例如,你可以将值存储在数组中,或者创建对象等。
释放内存:当你不再需要分配的内存时,应使用delete或delete[]操作符来释放它。忘记释放内存会导致内存泄漏,这是一个常见的编程错误。


4.2 代码示例


下面是一个简单的代码示例,演示了如何在C++中动态分配和释放内存:

 

#include <iostream>int main() {
// 步骤1:确定需要分配的内存大小
const int size = 10;// 步骤2:使用new操作符分配内存
int* array = new int[size];// 检查分配是否成功
if (array == nullptr) {
std::cerr << "Memory allocation failed!" << std::endl;
return 1; // 返回错误代码
}// 步骤3:使用分配的内存
for (int i = 0; i < size; ++i) {
array[i] = i;
}// 打印数组内容
for (int i = 0; i < size; ++i) {
std::cout << array[i] << " ";
}
std::cout << std::endl;// 步骤4:释放内存
delete[] array;return 0;
}


在这个示例中,我们首先确定要分配的内存大小(一个包含10个整数的数组)。然后,我们使用new操作符分配内存,并检查是否成功。接着,我们使用分配的内存来存储值,并打印数组的内容。最后,我们使用delete[]操作符来释放内存。

5.动态分配内存的分类及代码

在C++中,动态内存分配可以分为两类:动态分配单个对象的内存和动态分配对象数组的内存。



5.1 动态分配单个对象的内存


当你知道需要创建一个对象,但不知道它的生命周期时,可以使用new操作符动态地为其分配内存。这种分配方式在对象的大小不是固定大小时特别有用。



5.1.1 介绍


使用new为单个对象分配内存时,你需要指定对象的类型。new会返回指向新创建对象的指针。如果内存分配成功,你可以使用这个指针来访问和操作对象。如果内存分配失败,new会返回nullptr。



5.1.2 代码示例

 

#include <iostream>class MyClass {
public:
MyClass(int value) : value_(value) {}
void printValue() { std::cout << value_ << std::endl; }
private:
int value_;
};int main() {
// 动态分配单个对象的内存
MyClass* obj = new MyClass(42);// 使用对象
obj->printValue();// 释放内存
delete obj;return 0;
}


5.2 动态分配对象数组的内存


当你需要创建多个同类型的对象时,可以使用new操作符来动态分配一个对象数组。这种方式在你不确定数组大小,或者数组大小在运行时才能确定时非常有用。



5.2.1 介绍



使用new为对象数组分配内存时,你需要指定对象的类型和数组的大小。new会返回一个指向数组第一个元素的指针。与单个对象不同,当你使用new为数组分配内存时,需要使用delete[]来释放内存。



5.2.2 代码示例

 

#include <iostream>class MyClass {
public:
MyClass(int value) : value_(value) {}
void printValue() { std::cout << value_ << std::endl; }
private:
int value_;
};int main() {
// 动态分配对象数组的内存
const int arraySize = 5;
MyClass* array = new MyClass[arraySize];// 初始化数组中的对象
for (int i = 0; i < arraySize; ++i) {
array[i] = MyClass(i * 10);
}// 使用数组中的对象
for (int i = 0; i < arraySize; ++i) {
array[i].printValue();
}// 释放内存
delete[] array;return 0;
}


在上面的示例中,我们动态地创建了一个包含5个MyClass对象的数组,并分别初始化了它们。之后,我们遍历数组并打印每个对象的值。最后,我们使用delete[]释放了整个数组所占用的内存。



5.3 注意事项

1.使用new分配的内存必须使用delete或delete[]来释放,否则会导致内存泄漏。
2.new和delete是配对使用的,new[]和delete[]也是配对使用的。不应该混合使用它们,因为这会导致未定义的行为。
3.在使用new分配内存后,总是应该检查返回的指针是否为nullptr,以确保内存分配成功。
4.在C++11及以后的版本中,推荐使用智能指针(如std::unique_ptr和std::shared_ptr)来管理动态分配的内存,以自动处理内存释放,减少内存泄漏的风险。

6.动态分配内存的练习

6.1 题目描述



创建一个程序,该程序使用动态内存分配来创建一个字符串数组。用户将首先输入数组的大小,然后为每个字符串元素输入具体的字符串内容。程序将显示所有输入的字符串,并允许用户选择是否继续添加更多字符串或释放内存并退出程序。


6.2 知识点



动态内存分配与释放(new、delete[])
字符串处理(std::string):C++字符串详解
用户输入和输出(std::cin、std::cout)
循环结构(while、for):C++循环:简化重复的代码
条件语句(if、else):C++分支语句


6.3 步骤



6.3.1 初始化

设置必要的变量和标志,如数组大小、当前索引、是否继续的标志等。



6.3.2 输入数组大小

提示用户输入字符串数组的大小,并读取输入。



6.3.3 分配内存

使用new[]为字符串数组分配内存。



6.3.4 输入字符串内容

使用循环让用户为每个数组元素输入字符串内容。



6.3.5 显示字符串内容

使用循环显示所有输入的字符串。



6.3.6 用户选择

提供选项让用户决定是否继续添加字符串或退出程序。



6.3.7 释放内存

如果用户选择退出,释放已分配的内存。



6.3.8 结束程序

退出程序。



6.4 代码

 

#include <iostream>
#include <string>int main() {
int size;
std::cout << "Enter the size of the string array: ";
std::cin >> size;if (size <= 0) {
std::cerr << "Invalid array size. Size must be a positive integer." << std::endl;
return 1;
}std::string* arr = new std::string[size];
if (arr == nullptr) {
std::cerr << "Memory allocation failed!" << std::endl;
return 1;
}// 输入字符串内容
std::cout << "Enter " << size << " strings for the array:" << std::endl;
for (int i = 0; i < size; ++i) {
std::cin >> arr[i];
}// 显示字符串内容
std::cout << "The array contents are:" << std::endl;
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << std::endl;
}// 用户选择
char choice;
do {
std::cout << "Do you want to continue adding more strings? (y/n): ";
std::cin >> choice;
std::cin.ignore(); // 忽略换行符if (choice == 'y' || choice == 'Y') {
// 如果用户选择继续,再次分配内存并输入字符串
size *= 2; // 假设我们每次翻倍
std::string* newArr = new std::string[size];
for (int i = 0; i < size / 2; ++i) {
newArr[i] = arr[i];
}
delete[] arr;
arr = newArr;std::cout << "Enter " << size / 2 << " additional strings:" << std::endl;
for (int i = size / 2; i < size; ++i) {
std::cin >> arr[i];
}// 再次显示字符串内容(可选)
// ...} else if (choice == 'n' || choice == 'N') {
// 如果用户选择退出,释放内存并退出程序
std::cout << "Exiting program." << std::endl;
break;
} else {
std::cout << "Invalid choice. Please enter 'y' or 'n': " << std::endl;
}
} while (true);// 释放内存
delete[] arr;return 0;
}


这个程序演示了如何动态分配内存来创建一个字符串数组,如何让用户输入字符串内容,如何根据用户的选择动态调整数组大小,以及如何释放内存。同时,它也展示了基本的错误处理和用户交互。

7.总结

本篇博客到这里就结束了,感谢大家的支持与观看,如果有好的建议欢迎留言,谢谢大家啦!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2025.4.26总结

今天把马良老师的《职场十二法则》看完后&#xff0c;感触极大&#xff0c;这们课程就是一场职场启蒙课。 虽然看过不少关于职场的书籍&#xff0c;但大多数是关于职场进阶&#xff0c;方法方面的。并没有解答“面对未来二三十年的职场生涯&#xff0c;我该怎么去看待自己的工…

在Spring Boot项目中实现Word转PDF并预览

在Spring Boot项目中实现Word转PDF并进行前端网页预览&#xff0c;你可以使用Apache POI来读取Word文件&#xff0c;iText或Apache PDFBox来生成PDF文件&#xff0c;然后通过Spring Boot控制器提供文件下载或预览链接。以下是一个示例实现步骤和代码&#xff1a; 1. 添加依赖 …

计算机视觉——对比YOLOv12、YOLOv11、和基于Darknet的YOLOv7的微调对比

概述 目标检测领域取得了巨大进步&#xff0c;其中 YOLOv12、YOLOv11 和基于 Darknet 的 YOLOv7 在实时检测方面表现出色。尽管这些模型在通用目标检测数据集上表现卓越&#xff0c;但在 HRSC2016-MS&#xff08;高分辨率舰船数据集&#xff09; 上对 YOLOv12 进行微调时&…

Linux系统编程之内存映射

概述 内存映射是操作系统提供的一种机制&#xff0c;使得文件或设备的内容可以直接映射到进程的虚拟地址空间中。这意味着&#xff0c;我们可以像访问数组一样读写文件内容&#xff0c;而不需要显式地调用I/O函数进行数据传输。内存映射适用于多种应用场景&#xff0c;包括但不…

MyBatis XML 配置完整示例(含所有核心配置项)

MyBatis XML 配置完整示例&#xff08;含所有核心配置项&#xff09; 1. 完整 mybatis-config.xml 配置文件 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""htt…

Java 程序运行和类路径处理

PS D:\java_test> java .\java\Dog 错误: 找不到或无法加载主类 .\java\Dog 原因: java.lang.ClassNotFoundException: /\java\DogJava 程序运行和类路径处理 问题描述 在运行 Java 程序时&#xff0c;可能会遇到 ClassNotFoundException 错误&#xff0c;这是因为 Java 虚…

7.学习笔记-Maven进阶(P75-P89)-进度(p75-P80)

1.MAVEN-01-分模块开发的意义 &#xff08;一&#xff09;分模块开发意义 模块可以按功能划分&#xff0c;也可以按团队划分&#xff0c;所以把domain的方法抽取出来&#xff0c;进行共享&#xff0c;从而提高开发 的效率。 &#xff08;1&#xff09;分模块开发的意义&#xf…

CUDA编程之Grid、Block、Thread线程模型

一、线程模型:Grid、Block、Thread概念 ‌1. 层级定义‌ ‌Thread(线程)‌ CUDA中最基本的执行单元,对应GPU的单个CUDA核心(SP)。每个线程独立执行核函数指令,拥有独立的寄存器和局部内存空间‌。 ‌Block(线程块)‌ 由多个线程组成(通常为32的倍数),是逻辑上的并…

8. 深入Spring AI:自定义Advisor

1、前言 前面大篇幅介绍了关于Spring AI Advisor机制,并介绍了一些常见的内置的advisor。今天我们来自定义有一个Advisor。 2、快速开始 要自定义一个属于自己的Advisor,其实很自定义一个AOP一样简单。只需遵循以下步骤: 创建一个Advisor类,实现CallAroundAdvisor或Stre…

【C++】继承----下篇

文章目录 前言一、实现一个不能继承的类二、友元与继承三、继承与静态成员四、多继承以及菱形继承问题1.继承模型&#xff1a;2.菱形继承的问题3.虚拟继承解决数据冗余和二义性的原理4.虚拟继承的原理 五、继承的总结和反思1.继承和组合 总结 前言 各位好呀!今天呢我们接着讲继…

五一去荣昌吃卤鹅?基于Java和天地图的寻找荣昌卤鹅店实践

目录 前言 1、卤鹅哥与甲亢哥的爆火事件 2、荣昌卤鹅产业的空间分布 3、使用Java 和天地图进行产业挖掘 一、地名检索简介 1、地名检索功能 2、地名检索API介绍 二、荣昌卤鹅检索实践 1、数据获取流程 2、天地图API请求构建 3、参数构建及调用 4、结果生成及本地保存…

AI数字人:繁荣背后的伦理困境与法律迷局(8/10)

摘要&#xff1a;本文深入剖析 AI 数字人从虚拟走向现实的历程&#xff0c;阐述其融合多技术实现从静态到动态交互的跨越&#xff0c;爆发式应用于各领域带来的商业价值与社会影响&#xff0c;同时直面由此引发的伦理法律挑战&#xff0c;包括身份认同、数据隐私、责任归属及权…