C++学习---动态内存

news2024/12/22 14:29:24

文章目录

  • 堆和栈
  • new和delete操作符
  • 数组的动态内存分配
  • 对象的动态内存分配

堆和栈

在C++中

  • 栈:是一种静态内存分配区域,用于存储局部变量和函数调用的上下文信息。在栈上的内存分配和释放都是自动管理的,遵循后进先出(LIFO)原则。
  • 堆:是一种动态内存分配区域,用于存储动态分配的数据,如对象、数据和数据结构等,在堆上的内存分配和释放需要显式管理,例如使用new或malloc操作符来分配内存,使用delete和free等操作符来释放内存。

在很多时候,你无法提前预知需要多少内存来存储某个定义变量中的特定信息,所需内存的大小需要在运行时才能确定。

在 C++ 中,您可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址。这种运算符即 new 运算符。

如果您不再需要动态分配的内存空间,可以使用 delete 运算符,删除之前由 new 运算符分配的内存。


new和delete操作符

newdelete 运算符是C++中用于动态内存管理的操作符。它们允许你在堆上分配和释放内存,用于存储动态创建的对象和数据结构。

new 运算符:

  • new 运算符用于在堆上分配内存并构造一个对象。
  • 语法:new 数据类型new 数据类型[元素个数]
  • 对于单个对象的分配,new 返回指向该对象的指针。
  • 对于数组的分配,new 返回指向数组的首元素的指针。
  • 你需要手动释放使用 new 分配的内存,否则会导致内存泄漏。

例如,使用 new 创建一个整数对象的示例:

int* dynamicInt = new int; // 分配一个整数的内存
*dynamicInt = 42;

delete 运算符:

  • delete 运算符用于释放使用 new 分配的内存,并调用对象的析构函数(如果适用)。
  • 语法:delete 指针delete[] 指针
  • 你需要明确指定要释放的内存的指针,以避免悬挂指针问题。

例如,使用 delete 释放先前使用 new 分配的整数对象内存的示例:

delete dynamicInt; // 释放使用 new 分配的内存

newdelete 的数组形式:

你还可以使用 new[]delete[] 运算符来分配和释放动态数组的内存。在分配动态数组时,使用 new[],在释放内存时使用 delete[]。这些运算符对于分配和释放动态数组内存非常有用。

例如,使用 new[] 创建一个包含整数的数组,并使用 delete[] 释放内存的示例:

int* dynamicArray = new int[5]; // 分配一个包含 5 个整数的数组的内存
// 使用 dynamicArray 指向的内存
delete[] dynamicArray; // 释放使用 new[] 分配的数组内存

在C++中,可以通过检查指针是否为nullptr(空指针)来确定是否成功分配了内存。

例如:

int* dynamicInt = new int; // 尝试分配内存
if (dynamicInt != nullptr) {
    // 分配成功
    *dynamicInt = 42;
} else {
    // 分配失败
    // 执行错误处理逻辑
}

注:malloc() 函数在 C 语言中就出现了,在 C++ 中仍然存在,但建议尽量不要使用 malloc() 函数。new 与 malloc() 函数相比,其主要的优点是,new 不只是分配了内存,它还创建了对象。

完整的示例:

#include <iostream>

int main(){
    // 使用 new 分配内存并创建整数对象
    int* dynamicInt = new int;
    if (dynamicInt != nullptr){
        *dynamicInt = 42;
        std::cout << "Dynamic integer value: " << *dynamicInt << std::endl;
    } 
    else{
        std::cerr << "Memory allocation failed" << std::endl;
        return 1; // 退出程序,表示分配内存失败。
    }

    // 使用 delete 释放内存并销毁整数对象
    delete dynamicInt;

    return 0;
}

数组的动态内存分配

上面已经讲了关于new和delete的数组形式。扩展一下多维数组。

一维数组:

// 动态分配,数组长度为 m
int *array=new int [m];
 
//释放内存
delete [] array;

二维数组:

int **array;
// 假定数组第一维长度为 m, 第二维长度为 n
// 动态分配空间
array = new int *[m];
for( int i=0; i<m; i++ )
{
    array[i] = new int [n];
}
//释放
for( int i=0; i<m; i++ )
{
    delete [] array[i];
}
delete [] array;

示例:

#include <iostream>

int main() {
    int numRows = 3;
    int numCols = 4;

    // 动态分配二维数组
    int** dynamicArray = new int*[numRows]; // 分配行指针数组
    for (int i = 0; i < numRows; i++) {
        dynamicArray[i] = new int[numCols]; // 分配每行的列数组
    }

    // 初始化二维数组
    int count = 1;
    for (int i = 0; i < numRows; i++) {
        for (int j = 0; j < numCols; j++) {
            dynamicArray[i][j] = count++;
        }
    }

    // 打印二维数组
    for (int i = 0; i < numRows; i++) {
        for (int j = 0; j < numCols; j++) {
            std::cout << dynamicArray[i][j] << ' ';
        }
        std::cout << std::endl;
    }

    // 释放动态分配的内存
    for (int i = 0; i < numRows; i++) {
        delete[] dynamicArray[i]; // 释放每行的列数组
    }
    delete[] dynamicArray; // 释放行指针数组

    return 0;
}

三维数组:

int ***array;
// 假定数组第一维为 m, 第二维为 n, 第三维为h
// 动态分配空间
array = new int **[m];
for( int i=0; i<m; i++ )
{
    array[i] = new int *[n];
    for( int j=0; j<n; j++ )
    {
        array[i][j] = new int [h];
    }
}
//释放
for( int i=0; i<m; i++ )
{
    for( int j=0; j<n; j++ )
    {
        delete[] array[i][j];
    }
    delete[] array[i];
}
delete[] array;

示例:

#include <iostream>

int main() {
    int x = 3;
    int y = 4;
    int z = 2;

    // 动态分配三维数组
    int*** dynamicArray = new int**[x]; // 分配 x 个二维数组
    for (int i = 0; i < x; i++) {
        dynamicArray[i] = new int*[y]; // 分配每个二维数组的 y 行
        for (int j = 0; j < y; j++) {
            dynamicArray[i][j] = new int[z]; // 分配每行的 z 列
        }
    }

    // 初始化三维数组
    int count = 1;
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            for (int k = 0; k < z; k++) {
                dynamicArray[i][j][k] = count++;
            }
        }
    }

    // 打印三维数组
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            for (int k = 0; k < z; k++) {
                std::cout << dynamicArray[i][j][k] << ' ';
            }
            std::cout << std::endl;
        }
    }

    // 释放动态分配的内存
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            delete[] dynamicArray[i][j]; // 释放每行的列数组
        }
        delete[] dynamicArray[i]; // 释放每个二维数组的行指针数组
    }
    delete[] dynamicArray; // 释放 x 个二维数组的指针数组

    return 0;
}

对象的动态内存分配

示例:

#include <iostream>
using namespace std;

class Box
{
    public:
        Box(){
            cout << "调用构造函数!" << endl;
        }
        ~Box(){
            cout << "调用析构函数!" << endl;
        }
};

int main()
{
    Box* myBoxArray = new Box[4];

    delete [] myBoxArray; // 删除数组

    return 0;
}

如果要为一个包含四个 Box 对象的数组分配内存,构造函数将被调用 4 次,同样地,当删除这些对象时,析构函数也将被调用相同的次数(4次)。

当上面的代码被编译和执行时,它会产生下列结果:
在这里插入图片描述

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

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

相关文章

从vue源码中看diff算法

一、v-for必须要指定key&#xff0c;其作用是什么&#xff1f; 在源码中有一个函数为&#xff0c;其中就是通过判断两个vnode的type和key进行判断&#xff0c;如果这两个属性相同&#xff0c;那么这两个vnode就是相同&#xff0c;所以在设置key的时候也不可以设置为object等无…

基于SSM的二手车交易网站的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

网工内推 | 上市公司,云平台运维,IP认证优先,13薪

01 上海新炬网络信息技术股份有限公司 招聘岗位&#xff1a;云平台运维工程师 职责描述&#xff1a; 1、负责云平台运维&#xff0c;包括例行巡检、版本发布、问题及故障处理、平台重保等&#xff0c;保障平台全年稳定运行&#xff1b; 2、参与制定运维标准规范与流程&#x…

【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割5(训练篇)

在本系列的开篇&#xff0c;就对整个项目训练所需要的所有模块都进行了一个简要的介绍&#xff0c;尤其是针对训练中需要引入的各个结构&#xff0c;进行一个串联操作。 而在之前的数据构建篇和网络模型篇中&#xff0c;都对其中的每一个组块进行了分别的验证&#xff0c;预先…

python3+requests接口自动化测试框架

前段时间由于公司测试方向的转型&#xff0c;由原来的web页面功能测试转变成接口测试&#xff0c;之前大多都是手工进行&#xff0c;利用postman和jmeter进行的接口测试&#xff0c;后来&#xff0c;组内有人讲原先web自动化的测试框架移驾成接口的自动化框架&#xff0c;使用的…

MCU常见通信总线串讲(四)—— SPI总线协议

&#x1f64c;秋名山码民的主页 &#x1f602;oi退役选手&#xff0c;Java、大数据、单片机、IoT均有所涉猎&#xff0c;热爱技术&#xff0c;技术无罪 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 获取源码&#xff0c;添加WX 目录 前言一…

什么是API接口测试?这可能是全网最全的教程了!

什么是 API &#xff1f; API 是“应用程序编程接口”的缩写&#xff0c;是一种允许不同应用程序之间相互通信和交换数据的接口。就好像在餐厅点餐一样&#xff0c;你只需要告诉服务员你想要的食物&#xff0c;而不需要了解厨房中的具体操作&#xff0c;服务员会把你的订单传递…

深入asyncio:构建异步应用

文章目录 异步I/O操作示例:异步网络请求异步任务管理示例:并发执行多个任务使用异步队列示例:生产者-消费者模式在现代软件开发中,异步编程已经成为提高应用性能和响应性的关键技术之一。Python的asyncio库为编写单线程并发代码提供了强大的支持。本文将深入探讨asyncio的三…

CCF CSP认证 历年题目自练Day44

题目一 试题编号&#xff1a; 201612-3 试题名称&#xff1a; 权限查询 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   授权 (authorization) 是各类业务系统不可缺少的组成部分&#xff0c;系统用户通过授权机制获得系统中各个…

python教程:把多张图片,合并成一张图

D:\Wdpython\environment\Scripts\python.exe D:/Wdpython/爬虫/测试8.py 图片列表 10 [‘刘亦菲/刘亦菲_1.jpg’, ‘刘亦菲/刘亦菲_11.jpg’, ‘刘亦菲/刘亦菲_12.jpg’, ‘刘亦菲/刘亦菲_13.jpg’, ‘刘亦菲/刘亦菲_15.jpg’, ‘刘亦菲/刘亦菲_2.jpg’, ‘刘亦菲/刘亦菲_3.jp…

MacOS升级后命令行出现xcrun: error: invalid active developer path报错信息

在Mac上用g编译cpp文件时&#xff0c;出现以下&#xff08;类似于工具环境问题的&#xff09;报错&#xff1a; 解决方案&#xff1a;重新安装最新版的MacOS Command Line Tools xcode-select --install重新尝试编译&#xff1a; 编译成功&#xff08;忽略这个warning&…

搭建自己的MQTT服务器,实现设备上云(Ubuntu+EMQX)

一、EMQX介绍 这篇文章教大家在ECS云服务器上部署EMQX,搭建自己私有的MQTT服务器,配置EMQX实现设备上云,设备数据转发,存储;服务器我采用的华为云的ECS服务器,系统选择Ubuntu系统。 Windows版本的看这里: https://blog.csdn.net/xiaolong1126626497/article/details/1…

蓝桥杯每日一题2023.11.8

题目描述 题目分析 对于输入的abc我们可以以a为年也可以以c为年&#xff0c;将abc,cab,cba这三种情况进行判断合法性即可&#xff0c;注意需要排序去重&#xff0c;所以考虑使用set 此处为纯模拟的写法&#xff0c;但使用循环代码会更加简洁。 方法一&#xff1a; #include&…

servelt中请求路径的组成部分(Request Path Elements)

详情请参考&#xff1a;https://jakarta.ee/specifications/servlet/6.0/jakarta-servlet-spec-6.0.html#request-path-elements 请求路径包含下面几部分&#xff1a; Context Path&#xff1a;与ServletContext 关联的路径前缀。如果这个上下文是默认的上下文&#xff08;以…

定位内存溢出错误

添加虚拟机参数 -XX:HeapDumpOnOutOfMemoryError&#xff08;内存溢出则会自动生成"溢出分析文件"&#xff0c;如图1&#xff09; 图1 -Xmx512m&#xff08;为了快速模拟内存溢出&#xff0c;暂设堆空间为512m&#xff09; 编写发生内存溢出代码 public class Me…

计算机基础知识48

web应用程序 # Django框架是一款专门用来开发web应用的框架 # Web应用程序是一种可以通过浏览器访问的应用程序, B/S架构 案例&#xff1a;淘宝网、京东网... # 应用程序有两种模式: C/S&#xff1a;客户端/服务器端程序&#xff0c;这类程序一般独立运行 B/S&#xff1…

子查询,内查询 嵌套查询

子查询语句 一个查询语句中还有一个查询语句 Select&#xff0c;&#xff0c;&#xff0c;&#xff08;select&#xff09; 括号里的查询语句优先于查询语句执行&#xff0c;然后再把子查询的结果作为条件返回给主查询条件进行过滤 格式&#xff1a; #In Select 列名from …

leetcode刷题日记:94. Binary Tree Inorder Traversal(二叉树的中序遍历)

给出二叉树的根结点&#xff0c;返回二叉树的中序遍历序列。 二叉树的中序遍历序列是先遍历左子树再遍历根结点然后再遍历右子树&#xff0c;在遍历左子树是这个结点是左子树的根结点&#xff0c;左子树有左子树和根结点右子树&#xff0c;也就是说在遍历的时候我们要递归遍历。…

某XX自考小程序的AES加密分析

前言 主要是报了自考在这个小程序上面做题&#xff0c;就研究了一下这个接口本文仅供学习交流使用&#xff0c;请勿随意传播。如有侵犯你的权益及时联系我删除。 一、抓包分析打开小程序&#xff0c;打开devtools 工具&#xff0c;这里就不啰嗦&#xff0c;直接上过程。 点击…