C/C++动态内存分配 malloc、new、vector(简单讲述)

路虽远,行则将至

事虽难,做则必成

今天来主要讲C++中动态内存分配

其中会穿插一些C的内容以及两者的比较

如果对C语言中的动态内存分配还不够理解的同学

可以看看我之前的博客:C语言动态分配


在讲解C++的动态内存分配之前

我们先讲一下C++内存模型 :

C++内存分配模型

C++程序在执行时,将内存大方向划分为4个区域:


代码区:存放函数体的二进制代码,由操作系统进行管理的
全局区:存放全局变量和静态变量以及常量
栈区:由编译器自动分配释放,存放函数的参数值,局部变量
堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收



意义:不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程

栈区内存和堆区内存的区别

栈区内存是由编译器管理的,出了定义域就会被系统销毁

这里用代码展示:

#include<iostream>
using namespace std;
int* fun()
{int a = 10;              //局部变量存放在栈区,栈区的数据在函数执行完后释放return &a;               //返回变量a的地址
}
int main()
{int* p = fun();          //接受函数fun的返回值cout << "" << *p << endl;//这里能打印10是因为编译器在释放的会进行一次保留cout << "" << *p << endl;//这里出现乱码是因为空间被编译器销毁了system("pause");return 0;
}

 

1.第一次打印原值是因为编译器在释放时会进行一次保留

2.第二次出现乱码是因为出函数定义域空间被编译器销毁

由于栈区的内存出了定义域会被系统销毁不满足某些程序需求

于是我们引进了由程序员掌控的动态内存  


堆区内存(也就是我们说的动态内存)是由我们程序员分配的,由程序员进行管理

C++中动态内存开辟关键字new

我们可以通过newdelete(关键字)操作符进行动态内存管理

#include<iostream>
using namespace std;
int* fun()
{//利用new关键字可以将数据开辟到堆区int* p = new int(10);//动态申请一个int类型的空间并初始化为10return p;
}
int main()
{int* ptr = fun();cout << "" << *ptr << endl;cout << "" << *ptr << endl;delete ptr;//释放空间system("pause");return 0;
}

1.数据10是开辟在堆区的在程序没有结束之前是由程序员控制 

2.指针本质也是局部变量放在栈上指针保存的数据是放在堆区

 new还可以申请连续的空间:

#include<iostream>
using namespace std;
int main()
{int* a = new int[5];for (int i = 0; i < 5; i++){a[i] = i;}for (int i = 0; i < 5; i++){cout << "" << a[i] << endl;}delete[] a;system("pause");return 0;
}


注意:
申请和释放单个元素的空间,使用 new和delete
申请和释放连续的空间,使用new[]和delete[]
注意:匹配起来使用

 C&C++的动态开辟的区别

首先我们在介绍一下C语言中malloc开辟动态空间

#include<stdio.h>
#include<malloc.h>
#include<assert.h>
using namespace std;
int* fun()
{int* p = (int*)malloc(sizeof(int));//开辟空间assert(p);//断言开辟释放成功*p = 10;return p;
}
int main()
{int* ptr = fun();printf("%d\n", *ptr);printf("%d\n", *ptr);free(ptr);//释放空间system("pause");return 0;
}

 C&C++的动态开辟的区别:

相同点:

都是从堆上申请空间,并且需要用户手动释放

不同点:


1. malloc free 函数 new delete 操作符

2. malloc申请的空间不会初始化new可以初始化


3. malloc申请空间时,需要手动计算空间大小并传递new只需在其后跟上空间的类型即可

如果是多个对象,[]中指定对象个数即可

4. malloc的返回值为void*, 使用时必须强转new不需要,因为new后跟的是空间的类型


5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new

要捕获异常

 C++中vector开辟动态数组

template < class T, class Alloc = allocator<T> > class vector

容器的大小:vector是一个动态数组,可以根据需要自动调整大小一 它会根据素的数量动态分配内存空间


vector还可以使用一些功能:


vector增删查改
接口说明
push_back (重点) 尾插
pop_back   (重点) 尾删
find  查找(注意这个是算法模块实现,不是vector 的成员接口)
insert 在position 之前插入 val
erase 删除position 位置的数据
swap 交换两个vector 的数据空间
operator[ ]   (重点) 像数组一样访问

选代器

 vector提供了迭代器,可以用于遍历容器中的元素。可以使用 begin() 函数获取指向第个元素的迭代器,使用 end() 函数获取指向最后一个元素之后位置的迭代器


容器大小管理

可以使用 size() 函数获取vector中元素的数量,使用 empty() 函数检查vector是否为空


元素访问

可以通过索引来访闻vector中的元素。索引从0开始,最后一个元素的索引是 size 可以使用[]运算符或 at() 函数来访元素

接下来我们将介绍vector的常见用法(记得包含头文件#include <vector>哦):

vector的初始化(1)

vector开辟5个整型大小的连续空间,未赋初值

<>尖括号为元素类型名,它可以是任何合法的数据类型

#include<iostream>
#include<vector>
using namespace std;
int main()
{vector<int> a(5);//开辟动态数组for (int i = 0; i < 5; i++){a[i] = i;}for (int i = 0; i < 5; i++){cout << a[i] << " ";}return 0;
} 

 vector的初始化(2)

开辟5个整型大小的空间并赋值为1

#include<iostream>
#include<vector>
using namespace std;
int main()
{vector<int> a(5,1);for (int i = 0; i < 5; i++){cout << a[i] << " ";}return 0;
} 

vector的初始化(3)

vector<int> v = { 1,3,5,7,9,2,4,6,8,0 };

可以直接给动态数组赋初值

vector的常见用法(1):push_back

作用:将元素添加到vector的末尾

#include<iostream>
#include<vector>
using namespace std;
int main()
{vector<int> v;for (int i = 0; i < 10; ++i){v.push_back(i);//尾插}for (int i = 0; i < 10; ++i){cout << v[i] << " ";}return 0;
}

#include<iostream>
#include<vector>
using namespace std;
int main()
{vector<int> v;v.push_back(5);v.push_back(2);v.push_back(8);v.push_back(1);v.push_back(5);for (int i = 0; i < v.size(); i++)//size计算数组的长度{cout << v[i] << " ";}return 0;
}

vector的常见用法(2):迭代器

常用于排序

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{vector<int> v = { 1,3,5,7,9,2,4,6,8,0 };sort(v.begin(), v.end());for (int i = 0; i < v.size(); i++){cout << v[i] << " ";}return 0;
}

vector的常见用法(3):erase

常用于排序去重

首先,需要对vector进行排序,以便相同的元素相邻。

然后,unique函数将重复的元素移动到vector的末尾,并返回一个指向第一个重复元素的迭代器

最后,可以使用v.erase函数将重复元素从vector中删除

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{vector<int> v = { 2,1,3,2,4,1,5,4 };sort(v.begin(), v.end());            //排序:1 1 2 2 3 4 4 5auto rs = unique(v.begin(), v.end());//将重复元素丢在后面:1 2 3 4 5 1 2 4v.erase(rs, v.end());                //从第一个重复元素开始到结束的都删除for (const auto& num : v){cout << num << " ";}return 0;
}

vector的常见用法(4):empty

常用来检查vector是否为空

#include <iostream>
#include <vector>
using namespace std;
int main()
{vector<int> v;v.push_back(5);v.push_back(2);v.push_back(0);v.erase(v.begin() + 2);//删除位置3的元素if (v.empty()){cout << "vector为空" << endl;}else{cout << "vector不为空" << endl;}for (int i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << "\n";v.clear();//清空vector中的元素if (v.empty()){cout << "vector为空" << endl;}else{cout << "vector不为空" << endl;}return 0;
}

vector的常见用法(5):find

在任何容器中查找指定元素,返回一个迭代器指向第一个匹配的元素

常用于在一组数据中查找某一元素是否存在

#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main()
{vector<int> v = { 1,3,5,7,9,2,4,6,8,0};auto it = find(v.begin(), v.end(), 3);if (it != v.end())cout << "找到了元素 " << *it << '\n';elsecout << "找不到元素" << *it << '\n';
}

vector的常见用法(6):pop_back 

常用于删除末尾元素

#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main()
{vector<int> v = { 1,3,5,7,9,2,4,6,8,0};v.pop_back();v.pop_back();v.pop_back();for (int i = 0; i < v.size(); i++){cout << v[i] << " ";}return 0;
}

我们可以清晰的看到末尾的三个元素被删除了

vector的功能很强大,我感觉完全碾压malloc、new但是每个代码都有自己的运用场景

今天我们就介绍到这里啦

祝大家新年快乐 !!!

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

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

相关文章

CSS免费在线字体格式转换器 CSS @font-face 生成器

今天竟意外发现的一款免费的“网页字体生成器”&#xff0c;功能强大又好用~ 工具地址&#xff1a;https://transfonter.org/ 根据你设置生成后的文件预览&#xff1a; 支持TTF、OTF、WOFF、WOFF2 或 SVG字体格式转换生成&#xff0c;每个文件最大15MB。转换完成以后还会生成一…

宏集PC Runtime软件助推食品行业生产线数字化革新

一、前言 近年来&#xff0c;中国食品行业发展迅速且灵活多变&#xff0c;在当前经济下行的情形下&#xff0c;食品行业正面临着日益激烈的竞争&#xff0c;导致企业利润下降。 为了保持企业市场竞争力&#xff0c;国内某top10食品企业采用宏集SCADA解决方案—PC Runtime软件…

数学公式编译器MathType下载与安装

下载网址&#xff1a;下载 MathType - WIRIS Store 1.点击【下载MathType for Windows】 2、点击中文版 3.找到所下载的目录&#xff1a; 右击-->以管理员身份运行 4、新建word文档 点击文件->账户->关于word 5.点击【文件】、【选项】&#xff0c;❶点击【加载项】…

有趣的数学 为什么素数在密码学中很重要?

这里我们将探讨为什么素数在密码学中很重要。我们将根据特定的密码系统&#xff08; RSA 算法&#xff09;来进行深入了解。 一、素数的特殊性 每个数字都可以分解为它的素数。一般来说&#xff0c;找到一个数的因数是非常困难的。要找到一个自然数的所有素因数&#xff0c;必…

基于51单片机的激光竖琴设计

一、摘要 激光竖琴是一种将激光技术与音乐相结合的新型乐器&#xff0c;具有独特的音色和视觉效果。本文设计了一种基于51单片机的激光竖琴&#xff0c;通过对激光发射器的控制&#xff0c;实现对激光束的调制&#xff0c;从而产生不同的音高。系统主要包括51单片机控制模块、…

Zookeeper 分布式服务协调治理框架介绍入门

文章目录 为甚么需要Zookeeper一、Zookeeper 介绍1.1 介绍1.2 Zookeeper中的一些概念1.2.1 集群角色1.2.2 会话 session1.2.3 数据节点 Znode1.2.4 版本1.2.5 事件监听器 Watcher1.2.6 ACL 权限控制表(Access Control Lists) 二、 Zookeeper的系统模型2.1.1 ZNode节点2.1.2 ZNo…

C#的Char 结构的方法之IsLetterOrDigit()

目录 一、Char 结构 二、Char.IsLetterOrDigit 方法 1.定义 2.重载 3.示例 4.IsLetterOrDigit(Char) 5.IsLetterOrDigit(String, Int32) 一、Char 结构方法 CompareTo(Char)将此实例与指定的 Char 对象进行比较&#xff0c;并指示此实例在排序顺序中是位于指定的 Char …

基于ssm的班级事务管理系统+vue论文

摘 要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对班级事务信息管理的提升&#x…

【LeetCode:114. 二叉树展开为链表 | 二叉树 + 递归】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

STM32 基础知识(探索者开发板)--135讲 ADC转换

ADC定义&#xff1a; ADC即模拟数字转换器&#xff0c;英文详称 Analog-to-digital converter&#xff0c;可以将外部的模拟信号转换 ADC数模转换中一些常用函数&#xff1a; 1. HAL_ADC_Init 函数 HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *hadc); 初始化ADC 形参&…

洛谷 P1293 班级聚会

题目链接 分析 枚举每一个城市&#xff0c;并计算以他做聚会地点的价钱&#xff0c;取最小&#xff0c;如果相同则取最靠后的&#xff0c;时间复杂度为 Θ ( n 2 ) \Theta(n^2) Θ(n2)。 其实可以发现将城市 i i i 换到城市 i 1 i1 i1&#xff0c;那么 i i i 之前的包括…

数据库中的存储过程和函数

1、定义 存储过程和函数是事先经过编译并存储在数据库中的一段 SQL 语句的集合。 存储过程和函数是在数据库中预先定义并编译好的可复用代码块&#xff0c;可以用于完成特定的任务&#xff0c;如计 算、查询和变换等。 2、好处 提高代码的复用性。 减少数据在数据库和应用…

后端主流框架-SpringMvc-day2

Java中的文件下载 2 文件下载 文件下载&#xff1a;就是将服务器&#xff08;表现在浏览器中&#xff09;中的资源下载&#xff08;复制&#xff09;到本地磁盘&#xff1b; 2.1 前台代码 前台使用超链接&#xff0c;超链接转到后台控制器&#xff0c;在控制器通过流的方式…

AI:111-基于深度学习的工业设备状态监测

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…

Android 车联网——基础简介(一)

传统的车载功能单一,无太多娱乐性,而随着智能化时代的发展,车载系统也被赋予了在系统中预装 Android 应用的能力,基于Android平台的车载信息娱乐系统 —— Android AutoMotive 应运而生。 一、AutoMotive简介 Android Automotive OS 车载操作系统,是一个基本 Android 平台…

zsh配置

install sudo apt update sudo apt install zshsh -c "$(wget https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -)"chsh -s $(which zsh)安装 zsh-syntax-highlighting 插件&#xff1a; cd ~/.oh-my-zsh/custom/pluginsgit clone https://git…

技术与艺术的完美结合,AI艺术字生成平台一览

在创作的世界里&#xff0c;文字不仅是沟通的桥梁&#xff0c;更是灵魂的画笔。有时&#xff0c;我们的海报需要一丝文案的点缀&#xff0c;一些充满艺术感的文字&#xff0c;为作品注入更多的情感与深度。除了手写的文字&#xff0c;AI艺术字为我们提供了新的可能。AI生成未来…

WiFi7: MLO之概述

原文:MLO允许non-AP 和AP之间发现,认证,关联,建立1个或者多个Link。每个link独立的信道访问和帧交换。每个link的能力通过关联协商。 AP必须设置dot11MultiLinkActivated为真,必须附属于MLD。MLD和其附属的AP(s)必须受本规则限制。 Non-AP 当dot11MultiLinkActivated为真…

CF1909_C. Heavy Intervals题解

CF1909_C. Heavy Intervals题解 题目传送门&#xff08;Problem - C - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1909/problem/C&#xff09;。 题目翻译如下&#xff1a;&#xff08;图片来源&a…

操作系统期末复习!

引论及进程管理 1.操作系统的主要功能有( )。 A.进程管理、存储器管理、设备管理、处理机管理 B.虚拟存储管理、处理机管理、进程管理、文件管理 C.处理机管理、存储器管理、设备管理、文件管理 D.进程管理、中断管理、设备管理、文件管理 2.操作系统是对( )进行管…