C++---------动态内存管理

以下是对 C++ 中相关概念的详细说明及代码示例:

一、动态分配和堆

  1. new 操作符
    • new 操作符用于在堆上动态分配内存。它会调用对象的构造函数(如果是类对象)并返回指向分配内存的指针。
    • 示例:
#include <iostream>
using namespace std;

int main() {
    // 为一个整数分配内存
    int* p = new int;
    *p = 10;
    cout << *p << endl;
    // 释放内存
    delete p;
    return 0;
}
- 代码解释:
    - `int* p = new int;`:使用 `new` 操作符在堆上分配了足够存储一个 `int` 的内存空间,并将该内存地址存储在指针 `p` 中。
    - `*p = 10;`:将值 `10` 存储到 `p` 所指向的内存中。
    - `delete p;`:使用 `delete` 操作符释放之前分配的内存,防止内存泄漏。
  1. 动态数组
    • 使用 new 操作符可以创建动态数组,需要使用 delete[] 来释放。
    • 示例:
#include <iostream>
using namespace std;

int main() {
    int size = 5;
    // 为包含 5 个整数的数组分配内存
    int* arr = new int[size];
    for (int i = 0; i < size; ++i) {
        arr[i] = i * 2;
    }
    for (int i = 0; i < size; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;
    // 释放动态数组内存
    delete[] arr;
    return 0;
}
- 代码解释:
    - `int* arr = new int[size];`:在堆上分配了一个包含 `size` 个 `int` 元素的数组。
    - `for (int i = 0; i < size; ++i) { arr[i] = i * 2; }`:为数组元素赋值。
    - `delete[] arr;`:使用 `delete[]` 操作符释放动态数组的内存。

在这里插入图片描述

  1. 动态对象
    • 对于类对象,使用 new 操作符可以动态创建对象,同时会调用对象的构造函数。
    • 示例:
#include <iostream>
using namespace std;

class MyClass {
public:
    MyClass() {
        cout << "MyClass object is created." << endl;
    }
    ~MyClass() {
        cout << "MyClass object is destroyed." << endl;
    }
};

int main() {
    // 动态创建 MyClass 对象
    MyClass* obj = new MyClass();
    // 释放对象内存
    delete obj;
    return 0;
}
- 代码解释:
    - `MyClass* obj = new MyClass();`:在堆上创建 `MyClass` 的对象,调用其构造函数。
    - `delete obj;`:调用对象的析构函数并释放内存。

二、链表

  1. 链表内的迭代
    • 链表是一种动态数据结构,由节点组成,每个节点包含数据和指向下一个节点的指针。
    • 示例:
#include <iostream>
using namespace std;

struct Node {
    int data;
    Node* next;
    Node(int d) : data(d), next(nullptr) {}
};

int main() {
    Node* head = new Node(1);
    Node* second = new Node(2);
    Node* third = new Node(3);
    head->next = second;
    second->next = third;

    // 迭代链表
    Node* curr = head;
    while (curr!= nullptr) {
        cout << curr->data << " ";
        curr = curr->next;
    }
    cout << endl;

    // 释放链表内存
    curr = head;
    while (curr!= nullptr) {
        Node* temp = curr;
        curr = curr->next;
        delete temp;
    }
    return 0;
}
- 代码解释:
    - `Node` 结构体定义了链表的节点,包含 `data` 和 `next` 指针。
    - `head->next = second;` 和 `second->next = third;` 建立了链表的链接。
    - `while (curr!= nullptr) { cout << curr->data << " "; curr = curr->next; }`:通过迭代遍历链表并输出数据。
    - `while (curr!= nullptr) { Node* temp = curr; curr = curr->next; delete temp; }`:释放链表节点的内存。
  1. 递归和列表
    • 可以使用递归方法来处理链表,例如计算链表长度。
    • 示例:
#include <iostream>
using namespace std;

struct Node {
    int data;
    Node* next;
    Node(int d) : data(d), next(nullptr) {}
};

// 递归计算链表长度
int length(Node* head) {
    if (head == nullptr) return 0;
    return 1 + length(head->next);
}

int main() {
    Node* head = new Node(1);
    Node* second = new Node(2);
    Node* third = new Node(3);
    head->next = second;
    second->next = third;
    cout << "Length of the list: " << length(head) << endl;

    // 释放链表内存
    Node* curr = head;
    while (curr!= nullptr) {
        Node* temp = curr;
        curr = curr->next;
        delete temp;
    }
    return 0;
}
- 代码解释:
    - `length(Node* head)` 函数使用递归方法计算链表的长度,通过不断递归调用 `length(head->next)` 直到 `head` 为 `nullptr`。

三、释放内存

  1. delete 操作符

    • 用于释放 new 操作符分配的内存,确保在不再使用动态分配的内存时调用。
    • 对于对象使用 delete,对于数组使用 delete[]
    • 示例见上述动态分配和堆部分。
  2. 释放内存策略

    • 遵循“谁分配谁释放”原则,避免内存泄漏。在异常处理时也要确保正确释放内存。
    • 例如,在函数中分配的内存,在函数结束时或异常抛出时释放:
#include <iostream>
#include <stdexcept>
using namespace std;

void func() {
    int* p = new int;
    try {
        // 一些操作
        *p = 10;
        if (*p == 10) {
            throw runtime_error("Error occurred");
        }
        delete p;
    } catch (const exception& e) {
        delete p;
        throw;
    }
}

int main() {
    try {
        func();
    } catch (const exception& e) {
        cout << e.what() << endl;
    }
    return 0;
}
- 代码解释:
    - 在 `func()` 函数中,首先分配内存,在操作过程中可能抛出异常,使用 `try-catch` 确保在异常发生时也能正确释放内存。
  1. 析构函数
    • 析构函数是类的成员函数,当对象销毁时自动调用,用于释放资源。
    • 示例:
#include <iostream>
using namespace std;

class MyResource {
public:
    MyResource() {
        cout << "Resource acquired." << endl;
    }
    ~MyResource() {
        cout << "Resource released." << endl;
    }
};

class MyClass {
private:
    MyResource* res;
public:
    MyClass() {
        res = new MyResource();
    }
    ~MyClass() {
        delete res;
    }
};

int main() {
    MyClass obj;
    // 当 main 函数结束,obj 的析构函数会被调用,释放资源
    return 0;
}
- 代码解释:
    - `MyClass` 的构造函数中创建 `MyResource` 对象,析构函数中释放该对象,确保资源的释放。

四、定义 charstack 类

  1. charstack.h 接口
// charstack.h
#ifndef CHARSTACK_H
#define CHARSTACK_H

class CharStack {
private:
    char* stack;
    int top;
    int capacity;
    void resize();
public:
    CharStack();
    ~CharStack();
    void push(char c);
    char pop();
    bool isEmpty() const;
    bool isFull() const;
};

#endif
  1. 选择字符栈的表示
    • 这里选择动态数组表示字符栈,实现 charstack.cpp 如下:
// charstack.cpp
#include "charstack.h"
#include <iostream>

CharStack::CharStack() : top(-1), capacity(10) {
    stack = new char[capacity];
}

CharStack::~CharStack() {
    delete[] stack;
}

void CharStack::push(char c) {
    if (isFull()) {
        resize();
    }
    stack[++top] = c;
}

char CharStack::pop() {
    if (isEmpty()) {
        throw out_of_range("Stack is empty.");
    }
    return stack[top--];
}

bool CharStack::isEmpty() const {
    return top == -1;
}

bool CharStack::isFull() const {
    return top == capacity - 1;
}

void CharStack::resize() {
    capacity = capacity * 2;
    char* newStack = new char[capacity];
    for (int i = 0; i <= top; ++i) {
        newStack[i] = stack[i];
    }
    delete[] stack;
    stack = newStack;
}
- 代码解释:
    - `CharStack` 类使用动态数组存储字符元素。
    - `push(char c)` 方法将元素入栈,如果栈满调用 `resize()` 方法扩容。
    - `pop()` 方法将元素出栈,如果栈空抛出异常。
    - `resize()` 方法将栈的容量翻倍并复制元素到新的内存中。

在使用这些代码时,需要注意内存的分配和释放,避免出现内存泄漏。同时,对于类的设计,析构函数的正确使用可以确保资源的正确释放,以保证程序的健壮性和内存使用的合理性。
在这里插入图片描述

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

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

相关文章

企业该如何进行合格文件外发管理

随着信息技术的迅猛发展&#xff0c;企业间的文件交换变得越来越频繁。但是&#xff0c;如何确保文件传输的安全性与效率&#xff0c;成为企业管理者面临的一个重大挑战。镭速&#xff08;Raysync&#xff09;文件外发管理方案以其独特的优势&#xff0c;成为众多企业的首选。本…

Modbus数据网关在制造企业的应用与效果

Modbus是一种广泛应用于工业通信的协议&#xff0c;支持多种设备间的数据交换&#xff0c;如传感器、仪器仪表、PLC、工业机器人、数控机床等。Modbus数据网关则是一种网络通信转换设备&#xff0c;它能够将Modbus协议的数据转换为其他主流协议&#xff08;如MQTT、OPC UA、HTT…

解决集群Elasticsearch 未授权访问漏洞

1、ES集群配置 首先至少是三个节点 2、生成证书&#xff08;后面要用&#xff09; cd /home/elasticsearch-7.4.2/bin ./elasticsearch-certutil cert 回车&#xff0c;空密码&#xff08;可以输入密码&#xff09;&#xff0c;回车 3、将elastic-certificates.p12 复制到三…

mac启ssh服务用于快速文件传输

x.1 在mac上启SSH服务 方法一&#xff1a;图形交互界面启ssh&#xff08;推荐&#xff09; 通过sharing - advanced - remote login来启动ssh&#xff1b;&#xff08;中文版mac应该是 “系统设置 → 通用 → 共享”里打开“远程登录”来启动&#xff09; 查看自己的用户名和…

Jenkins 任意文件读取(CVE-2024-23897)修复及复现

Jenkins任意文件读取漏洞CVE-2024-23897修复及复现 漏洞详情影响范围漏洞复现修复建议 Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软件项目可以进行…

C语言数组查找

数组概念 就是一堆数的一个集合&#xff0c;包含于指针&#xff0c;但是与指针不同的是数组是开辟了空间的 char a[20] //开辟了20个空间 char *p //一个指针&#xff0c;并没有开辟空间 数组名作为指针&#xff1a; 在C语言中&#xff0c;数组名通常可以被看作是一…

HarmonyOS NEXT 实战之元服务:静态案例效果---最近播放音乐

背景&#xff1a; 前几篇学习了元服务&#xff0c;后面几期就让我们开发简单的元服务吧&#xff0c;里面丰富的内容大家自己加&#xff0c;本期案例 仅供参考 先上本期效果图 &#xff0c;里面图片自行替换 效果图1完整代码案例如下&#xff1a; Index import { authentica…

CVPR2024 | DiffAM:基于扩散模型的对抗性化妆迁移用于面部隐私保护

DiffAM: Diffusion-based Adversarial Makeup Transfer for Facial Privacy Protection 摘要-Abstract引言-Introduction相关工作-Related Works人脸识别中的对抗攻击化妆迁移扩散模型和风格迁移 方法-Method问题表述DiffAM文本引导的化妆去除图像引导的对抗性化妆转移 实验-Ex…

ffmpeg之播放一个yuv视频

播放YUV视频的步骤 初始化SDL库&#xff1a; 目的&#xff1a;确保SDL库正确初始化&#xff0c;以便可以使用其窗口、渲染和事件处理功能。操作&#xff1a;调用 SDL_Init(SDL_INIT_VIDEO) 来初始化SDL的视频子系统。 创建窗口用于显示YUV视频&#xff1a; 目的&#xff1a;…

Java高级工程师1380道面试题(附答案)分享

Java 面试八股文有必要背吗&#xff1f; 我的回答是&#xff1a;很有必要。你可以讨厌这种模式&#xff0c;但你一定要去背&#xff0c;因为不背你就进不了大厂。现如今&#xff0c;Java 面试的本质就是八股文&#xff0c;把八股文面试题背好&#xff0c;面试才有可能表现好。…

打造高效租赁小程序让交易更便捷

内容概要 在如今节奏飞快的商业世界里&#xff0c;租赁小程序如同一只聪明的小狐狸&#xff0c;迅速突围而出&#xff0c;成为商家与消费者之间的桥梁。它不仅简化了交易流程&#xff0c;还在某种程度上将传统租赁模式带入了互联网时代。越来越多的企业意识到&#xff0c;这种…

VS2022 无法使用GitHub账户登录/无法使用copilot 解决方案

无法登录github 账户 错误提示如下&#xff1a; We encountered an issue while adding your GitHub account. Exception Type: GitHubSignInException. Inner Exception: StreamJsonRpc.RemoteInvocationException. Error Message: The input is not a valid Base-64 str…

前端样式练手:阴阳图+时钟的组合

开篇 今天的小作品是突然脑子灵光一闪写出来的&#xff0c;代码不多&#xff0c;就不过多赘述了。 代码实现 <template><div class"clock-container"><!-- 八卦图 --><!-- <div class"bagua"><divv-for"(trigram, ind…

对话 Project Astra 研究主管:打造通用 AI 助理,主动视频交互和全双工对话是未来重点

Project Astra 愿景之一&#xff1a;「系统不仅能在你说话时做出回应&#xff0c;还能在持续的过程中帮助你。」 近期&#xff0c;Google DeepMind 的 YouTube 频道采访了 Google DeepMind 研究主管格雷格韦恩 (Greg Wayne)。 格雷格韦恩的研究工作为 DeepMind 的诸多突破性成…

Maven 项目文档

如何创建 Maven 项目文档。 比如我们在 C:/MVN 目录下&#xff0c;创建了 consumerBanking 项目&#xff0c;Maven 使用下面的命令来快速创建 java 项目&#xff1a; mvn archetype:generate -DgroupIdcom.companyname.bank -DartifactIdconsumerBanking -DarchetypeArtifact…

目标检测——基于yolov8和pyqt的螺栓松动检测系统

目录 1.项目克隆和环境配置1.1 我这里使用的是v8.0.6版本1.2 项目代码结构介绍 2.数据集介绍2.1 数据集采集2.2采集结果介绍 3.模型训练4.pyqt界面设计4.1 界面内容介绍4.2 界面实现 5.操作中的逻辑实现5.1 图片检测5.2 文件夹检测5.3 视频检测和摄像头检测 6. 效果展示 1.项目…

HTTP 协议、AJAX - 异步网络请求及跨域、同源策略

文章目录 一、HTTP 协议简述1. 协议的基本理解2. HTTP 协议的数据格式 二、Express 服务器1. Express 服务器的安装和启动2. Express 服务器的基本使用 三、AJAX 异步网络请求1. ES5 的 XMLHttpRequest 对象实现 AJAX 异步网络请求2. 利用 jQuery 库实现 AJAX 异步网络请求3. E…

使用 OpenCV 绘制线条和矩形

OpenCV 是一个功能强大的计算机视觉库&#xff0c;它不仅提供了丰富的图像处理功能&#xff0c;还支持图像的绘制。绘制简单的几何图形&#xff08;如线条和矩形&#xff09;是 OpenCV 中常见的操作。在本篇文章中&#xff0c;我们将介绍如何使用 OpenCV 在图像上绘制线条和矩形…

【每日学点鸿蒙知识】上架流程、h5返回收拾拦截、两个枚举类型之间转换、hvigorw命令、绘制本地图片

1、HarmonyOS 上架流程&#xff1f; 上架流程&#xff0c;请参考文档&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-publish-app-V5 上架的一些条件&#xff0c;也请 这边悉知&#xff0c;参考链接&#xff1a;https://developer.huawe…

使用腾讯云CVM搭建 K8s + Docker + Harbor :部署SpringBoot应用与配置指南

在现代云原生应用的开发和部署过程中&#xff0c;容器化技术已经成为主流&#xff0c;而 Kubernetes&#xff08;K8s&#xff09;则是容器编排的绝对领导者。为了高效地管理和分发容器镜像&#xff0c;拥有一个可靠的私有镜像仓库是每个开发者和运维工程师不可或缺的工具。Dock…