C++笔记之动态数组的申请和手动实现一个简单的vector

news2024/11/24 4:01:50

C++笔记之动态数组的申请和手动实现一个简单的vector

code review!

文章目录

  • C++笔记之动态数组的申请和手动实现一个简单的vector
    • 1.C语言中动态数组的申请与使用
    • 1.动态数组的申请
      • 使用`new`和`delete`
      • 使用`std::vector`
    • 1.std::vector的底层实现
    • 2.手动实现一个简单的vector:使用一个指向动态分配的数组的指针来存储元素模拟vector的基本行为

1.C语言中动态数组的申请与使用

在C语言中,可以使用malloc函数来动态申请内存以创建动态数组,并使用free函数来释放这些内存。以下是在C语言中创建和使用动态数组的基本示例:
在这里插入图片描述

代码

#include <stdio.h>
#include <stdlib.h>

int main() {
    int size;
    printf("Enter the size of the dynamic array: ");
    scanf("%d", &size);

    // 使用malloc函数分配动态数组内存
    int *dynamicArray = (int *)malloc(size * sizeof(int));

    // 检查内存分配是否成功
    if (dynamicArray == NULL) {
        printf("Memory allocation failed.\n");
        return 1; // 返回错误码
    }

    // 初始化动态数组的元素
    for (int i = 0; i < size; i++) {
        dynamicArray[i] = i * 2;
    }

    // 访问和使用动态数组的元素
    for (int i = 0; i < size; i++) {
        printf("%d ", dynamicArray[i]);
    }

    // 释放动态数组内存
    free(dynamicArray);

    return 0;
}

在上述示例中,首先使用malloc函数分配了一块内存,该内存可以存储sizeint类型的元素。然后,通过循环初始化和使用动态数组的元素。最后,使用free函数释放分配的内存以防止内存泄漏。

请注意,使用mallocfree来管理内存需要特别小心,确保在不再需要动态数组时释放内存,以免出现内存泄漏。此外,动态数组的内存大小必须在运行时明确定义,并且需要手动处理分配和释放内存,这可能会引入错误,因此要特别小心。如果可能的话,推荐使用C++中的std::vector或C语言的动态数组分配方式,如allocastrdup,以减少手动内存管理的复杂性。

1.动态数组的申请

在C++中,可以使用new运算符来动态申请数组,并使用delete运算符来释放它们。此外,C++11引入了std::vector,它是一个动态数组的封装,提供了更方便和安全的方法来管理动态数组。下面分别介绍使用newstd::vector的方法来创建和使用动态数组。

使用newdelete

在这里插入图片描述

代码

#include <iostream>

int main() {
    int size;
    std::cout << "Enter the size of the dynamic array: ";
    std::cin >> size;

    // 通过new运算符分配动态数组
    int* dynamicArray = new int[size];

    // 初始化动态数组的元素
    for (int i = 0; i < size; i++) {
        dynamicArray[i] = i * 2;
    }

    // 访问和使用动态数组的元素
    for (int i = 0; i < size; i++) {
        std::cout << dynamicArray[i] << " ";
    }

    // 释放动态数组内存
    delete[] dynamicArray;

    return 0;
}

使用new分配动态数组后,不要忘记使用delete[]释放内存,以防止内存泄漏。

使用std::vector

使用std::vector可以更方便地管理动态数组,无需手动分配和释放内存:

#include <iostream>
#include <vector>

int main() {
    int size;
    std::cout << "Enter the size of the dynamic array: ";
    std::cin >> size;

    // 使用std::vector创建动态数组
    std::vector<int> dynamicArray(size);

    // 初始化动态数组的元素
    for (int i = 0; i < size; i++) {
        dynamicArray[i] = i * 2;
    }

    // 访问和使用动态数组的元素
    for (int i = 0; i < size; i++) {
        std::cout << dynamicArray[i] << " ";
    }

    return 0;
}

std::vector会自动处理内存分配和释放,使得代码更加安全和易维护。

无论您选择使用newdelete还是std::vector,都要确保正确管理动态数组的内存,以防止内存泄漏和访问越界错误。

1.std::vector的底层实现

C++中的vector是标准库中的一个动态数组容器,它提供了动态大小的数组,类似于C数组,但它具有自动管理内存的功能,可以动态增加或减少数组的大小。vector的底层实现通常是使用动态分配的数组,以及一些成员函数来管理这个数组的大小和元素。

下面是vector的一些常见底层实现细节:

  1. 动态分配的数组:vector内部通常使用一个指向动态分配的数组的指针来存储元素。这个数组的大小可以根据vector中存储的元素数量动态调整。当元素数量超过当前数组的容量时,vector会分配一个更大的数组,将元素从旧数组复制到新数组,然后释放旧数组。

  2. 容量(Capacity)和大小(Size):vector有两个重要的属性,容量和大小。容量表示当前数组的大小,而大小表示vector中实际存储的元素数量。容量通常大于或等于大小,因为vector可能会提前分配一些额外的空间,以减少频繁重新分配内存的开销。

  3. 动态调整容量:当vector的大小超过容量时,它会重新分配更大的内存块,并将元素从旧数组复制到新数组。这通常涉及到内存分配和复制操作,这可能会导致性能开销。为了减小重新分配的频率,vector通常会分配比当前大小更多的额外空间,以避免在每次插入元素时都重新分配内存。

  4. 内存管理:vector负责动态内存的分配和释放,以确保内存的正确管理。当vector不再需要某个内存块时,它会调用delete[]allocator::deallocate来释放内存。

  5. 迭代器:vector提供了迭代器,用于访问容器中的元素。迭代器是指向容器中元素的指针或对象,允许你遍历vector的内容。

总之,vector的底层实现是基于动态分配的数组,它使用内部指针来管理内存,并提供了各种方法来操作容器中的元素,包括插入、删除、访问等。这些实现细节在C++标准库中是隐藏的,因此你可以方便地使用vector而无需担心底层实现的细节。

2.手动实现一个简单的vector:使用一个指向动态分配的数组的指针来存储元素模拟vector的基本行为

在这里插入图片描述

运行
在这里插入图片描述

代码

#include <iostream>

class MyVector {
public:
    MyVector() : data(nullptr), size(0), capacity(0) {}

    void push_back(int value) {
        if (size >= capacity) {
            // 如果当前大小超过容量,需要重新分配更大的内存
            int new_capacity = (capacity == 0) ? 1 : capacity * 2;
            int* new_data = new int[new_capacity];

            // 将数据从旧数组复制到新数组
            for (int i = 0; i < size; i++) {
                new_data[i] = data[i];
            }

            // 释放旧数组的内存
            delete[] data;

            // 更新指针和容量
            data = new_data;
            capacity = new_capacity;
        }

        // 在数组末尾添加新元素
        data[size] = value;
        size++;
    }

    int at(int index) {
        if (index >= 0 && index < size) {
            return data[index];
        } else {
            std::cerr << "Index out of range!" << std::endl;
            return -1;
        }
    }

    int getSize() {
        return size;
    }

    ~MyVector() {
        delete[] data; // 释放动态分配的内存
    }

private:
    int* data;      // 指向动态分配的数组的指针
    int size;       // 当前元素数量
    int capacity;   // 当前容量
};

int main() {
    MyVector vec;

    // 向自定义的vector中添加一些元素
    for (int i = 1; i <= 10; i++) {
        vec.push_back(i * 10);
    }

    // 访问元素并打印
    for (int i = 0; i < vec.getSize(); i++) {
        std::cout << "Element at index " << i << ": " << vec.at(i) << std::endl;
    }

    return 0;
}

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

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

相关文章

项目实战:展示第一页数据

1、在FruitDao接口中添加查询第一页数据和查询总记录条数 package com.csdn.fruit.dao; import com.csdn.fruit.pojo.Fruit; import java.util.List; //dao &#xff1a;Data Access Object 数据访问对象 //接口设计 public interface FruitDao {void addFruit(Fruit fruit);vo…

文件复制加密、文件落地加密、文件移动加密如何设置?

文件加密在保护信息安全方面具有重要作用。合格、好用的文件加密软件可以帮助企业保护商业机密、更遵守法律法规、提高企业核心竞争力、防止数据泄密等。 一般的加密都是对文件本身加密&#xff0c;比如加密某个WORD /PPT之类的&#xff0c;很少有能够加密某个文件夹的。今天就…

单链表基本操作的实现,初始化,头插,尾插,判空,获取个数,查找,删除,获取前置和后置位,清空,销毁

目录 一.单链表的设计 二.单链表的实现 三.单链表的总结 一.单链表的设计 1.单链表的结构定义: typedef struct Node{int data;//数据域struct Node* next;//后继指针}Node,*List; 2.单链表的设计示意图: 3.注意,单链表的最后一个节点的next域为NULL; 4.为什么要有一个头…

唯一ID如何生成,介绍一下目前技术领域最常使用的几种方法

纵使十面大山&#xff0c;又如何&#xff0c;无妨… 概述 唯一ID&#xff08;Unique Identifier&#xff09;是在计算机科学和信息技术领域中用于标识某个实体或数据的唯一标识符。生成唯一ID的方法可以根据具体需求和应用场景的不同而有所不同。以下是一些目前技术领域中常用…

2023-mac rz sz 安装

之前安装过一次&#xff0c;没问题&#xff0c;这次按照之前教程装了就不管上传下载都会卡住&#xff1b; step1: brew install lrzsz step2&#xff1a;在/usr/local/bin 路径下配置两个sh,之前从网上找到的直接用都不对&#xff0c;下面这个是调试过的正式可用的 iterm2…

【C语言进阶】之动态内存管理

【C语言进阶】之动态内存管理 1.为什么我们需要动态内存管理2.动态内存管理的函数介绍2.1malloc函数和free函数2.1.1malloc函数2.1.2 free函数 2.2calloc函数2.3realloc函数 3.动态内存管理中经常出现的一些问题总结。3.1 越界访问3.2 对空指针进行解引用操作3.3 对同一片空间进…

安全防御——二、ENSP防火墙实验学习

安全防御 一、防火墙接口以及模式配置1、untrust区域2、trust区域3、DMZ区域4、接口对演示 二、防火墙的策略1、定义与原理2、防火墙策略配置2.1 安全策略工作流程2.2 查询和创建会话 3、实验策略配置3.1 trust-to-untrust3.2 trust-to-dmz3.3 untrust-to-dmz 三、防火墙的区域…

归并排序--C语言实现

1. 简述 归并排序的原理是将&#xff0c;两个较大的数组分为大小几乎一致的两个数组。 再将两个数组进行合并成新的有序数组。 合并两个数组的时候需要额外的一个数组的空间。 2. 实现 上图说明过程 代码 #include <stdio.h>void Merge(int *arr, int *tmp, int …

freertos入门(stm32f10c8t6版闪烁灯)

首先到官网下载freertos源码&#xff0c;然后找一个stm32f10c8t6的空模板&#xff0c;这个空模板实现点灯之类的都行。 然后在这个空模板的工程下新建一个FreeRtos文件夹 接着在FreeRtos文件夹下新建三个文件夹&#xff0c;分别是src存放源码 inc 存放头文件&#xff0c;port …

Linux下查看文件夹大小命令

在Vscode上连接服务器&#xff0c;想查看文件夹大小&#xff1b; du -h path

4 个最常见的自动化测试挑战及应对措施

有人说&#xff1a;“杂乱无章的自动化只会带来更快的混乱。”不仅更快&#xff0c;而且是更严重、更大的混乱。如果使用得当&#xff0c;自动化可以成为测试团队中令人惊叹的生产力助推器和系统的质量增强器。自动化测试的关键是要正确运用&#xff0c;这是初始最困难的部分。…

动态路由协议OSPF优化提速特性

1.OSPF协议通信过程与部署&#xff1b; 2.OSPF协议在项目上的应用场景&#xff1b; 3.OSPF有哪些优化特性&#xff1f; - OSPF - 开放式最短路径优先 - 一个动态路由协议 - 路由协议 - 理解魏 运行在路由器的一个软件 - 目的&#xff1a;为了帮助路由器和路由器彼…

短期经济波动:均衡国民收入决定理论(二)

短期经济波动:国民收入决定理论(二) 文章目录 短期经济波动:国民收入决定理论(二)[toc]1 IS曲线1.1 IS曲线的代数推导1.1.1 代数法&#xff1a;计划支出等于实际支出1.1.2 代数法&#xff1a;计划投资等于储蓄1.1.3 代数法&#xff1a;非计划存货等于0 1.2 IS曲线的几何推导1.2…

ZZ038 物联网应用与服务赛题第D套

2023年全国职业院校技能大赛 中职组 物联网应用与服务 任 务 书 (D卷) 赛位号:______________ 竞赛须知 一、注意事项 1.检查硬件设备、电脑设备是否正常。检查竞赛所需的各项设备、软件和竞赛材料等; 2.竞赛任务中所使用的各类软件工具、软件安装文件等,都…

如何理解所谓的【指令执行速度】

公式&#xff1a; 指令执行速度 主频/平均CPI 先不看主频&#xff0c;如下图&#xff0c;假设一秒钟能有4个正弦波&#xff0c;那就说明频率是4。 而计算机很厉害&#xff0c;一秒能有很多个正弦波 把一个正弦波&#xff0c;看做一个时钟周期 则主频表示&#xff0c;计算机…

《视觉SLAM十四讲》-- 概述与预备知识

文章目录 01 概述与预备知识1.1 SLAM 是什么1.1.1 基本概念1.1.2 视觉 SLAM 框架1.1.3 SLAM 问题的数学表述 1.2 实践&#xff1a;编程基基础1.3 课后习题 01 概述与预备知识 1.1 SLAM 是什么 1.1.1 基本概念 &#xff08;1&#xff09;SLAM 是 Simultaneous Localization a…

【算法|二分查找No.2】leetcode 69. x 的平方根

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

Python基础入门例程29-NP29 用列表实现栈(列表)

最近的博文&#xff1a; Python基础入门例程28-NP28 密码游戏&#xff08;列表&#xff09;-CSDN博客 Python基础入门例程27-NP27 朋友们的喜好&#xff08;列表&#xff09;-CSDN博客 Python基础入门例程26-NP26 牛牛的反转列表&#xff08;列表&#xff09;-CSDN博客 目录…

0.专栏概述与几句闲话

引 还记得今年大年初一开始写《数据结构和算法》专栏的时候定了个小目标&#xff1a; 不知不觉间已经过去了十个月&#xff0c;我的第一个专栏也算是圆满收官了 。 这次PO一张成都熊猫基地的团子们&#xff0c;开启设计模式这个专栏吧。 目录与概述 犹记得一位身在广州的老…

CAN报文的信号和信号组传递的意义

CAN将数据发送到COM层&#xff0c;在这个过程中报文是如何传递的&#xff1f; 0x105指的是一帧CAN报文&#xff0c;信号组指的是一帧CAN报文里的所有数据&#xff0c;信号指的是一帧CAN报文里的每一个信号&#xff0c;PDU代表了一帧CAN报文&#xff0c;它由报文ID&#xff08;I…