数组内存分配概念

2023-05-16

在这里解答一下:

int arr[4];

&arr[1] = arr[0] + sizeof(int) ;


静态分配, 即普通数组, 由于在栈中分配, 而栈的生成方向是自高地址向低地址生成。 所以有:

&arr[0] > &arr[1] ....

动态分配的数组。针对动态数组。 动态数组的内存分配在heap中。 而heap 的生成是由低地址向高地址生成。 所以有:

&arr[0] < &arr[1] <...

这是我以为的。  答案是我我错了。

测试一下:

[cpp] view plain copy print ?
  1. #include <iostream>  
  2.   
  3.   
  4. using namespace std;  
  5.   
  6.   
  7.   
  8.   
  9. int main() {  
  10.    int n = 4;  
  11.    int *ptr = new int[n];  
  12.   
  13.   
  14.    // dynamic array: on heap  
  15.        cout << "dynamic array: " << endl;  
  16.    for(int i = 0; i < 4; ++i) {  
  17.        cout << &ptr[i] << endl;  
  18.    }  
  19.   
  20.   
  21.    // ordinary array: on stack  
  22.    int arr[4];  
  23.    cout << "ordinary array: " << endl;  
  24.    for(int i = 0; i < 4; ++i) {  
  25.        cout << &arr[i] << endl;  
  26.    }  
  27.    return 0;  
  28. }  
#include <iostream>


using namespace std;




int main() {
   int n = 4;
   int *ptr = new int[n];


   // dynamic array: on heap
       cout << "dynamic array: " << endl;
   for(int i = 0; i < 4; ++i) {
       cout << &ptr[i] << endl;
   }


   // ordinary array: on stack
   int arr[4];
   cout << "ordinary array: " << endl;
   for(int i = 0; i < 4; ++i) {
       cout << &arr[i] << endl;
   }
   return 0;
}

结果如下:



为什么无论是静态数组还是动态数组, 数组元素的分配都是对元素从低地址到高地址。 

  无论动态还是静态 地址都是arr[0] < arr[1] 也就是数组内存是统一分配的
内部元素都是从低地址到高地址 。 
 
 
 
 
 
 

1、内存分配的三种方式:

1)、从静态存储区分配。数据的内存在程序编译时已经被分配,该内存在整个运行期间长期驻留,不会被释放;程序结束时,由操作系统自动释放。这类数据包括静态数据和全局数据。

2)、从栈空间分配。函数执行过程中,函数中的局部变量的内存,在栈上被分配;当函数调用完成后,随函数的返回空间也被释放。

3)、从堆空间分配。由开发者动态的申请内存,并手动的释放内存。

本文具体介绍动态内存分配,C语言中采用malloc、recalloc等函数分配内存;c++中使用new操作符申请内存。

malloc函数的返回值为void*,调用该函数时,需要显式的类型转化。返回值表示内存空间的首地址。如果该地址为NULL,表示系统没有满足的内存可供分配。因此在使用该地址之前,必须判断是否分配成功。例如:

int*p=(int*)malloc(sizeof(int)*10);

if(p != NULL)

{

......//使用该内存空间

}

在该内存使用完成后,需要开发者手动释放该内存:free(p):

这里需要注意:1)、调用free后,p和所指向的内存地址被断开,但是p的值仍然没有变化,此时如果调用p,将会出现错误,这时p就是一个野指针;因此当free(p);之后,应该将p的值赋为NULL,以免p再次调用出现错误。2)、虽然内存已经分配完成,但是并没有初始化,直接使用,取到的结果不正确。

4)、当malloc申请的内存不满足用户使用要求时,就需要重新分配内存,这时可以使用realloc函数。


  

void *realloc(
   void *memblock,
   size_t size 
);  
memblock参数表示已经分配的内存地址的指针,即就是p;

size参数表示需要分配的字节数

该函数的返回值为,重新分配的内存空间的首地址。

realloc函数,在malloc函数已经分配的内存基础上再次扩充内存。realloc函数的返回值类型仍为void*。可以分三种情况来解释realloc。

情况一:需要分配的内存空间小于已经分配的空间。

那么这时只是从原来已经分配的内存空间中,将多余的空间释放,保留realloc函数需要的空间大小,将原来空间的的首地址赋值给realloc函数返回(这个地址和p的值是相同的);如果这样做的,可能会导致数据出错,因此一般不要缩小原内存空间;

情况二:需要分配的内存空间等于已经分配的空间。

将原来内存空间的首地址赋值给realloc函数返回;

情况三:需要分配的内存空间大于已经分配的空间。

1)如果原来的内存后,还有足够的空间,满足分配要求,那么直接在原来的内存的后面,分配适量的空间,并将原来空间的首地址赋值给realloc函数,返回;

2)如果原来内存后,没有足量的内存空间,满足分配要求,那么重新选择一块足量的空间分配,并将原来已经分配的空间的数据拷贝到新分配的内存中,将原指针p指向的空间释放。将新分配的空间首地址赋值给realloc函数返回,因此对于原来的空间,realloc函数在分配内存时,已经释放了原来的内存,不需要再次释放,否则会出错。

情况四:当分配的内存大小为0

系统是可以返回一个非NULL值,但是这个空间不能被使用。使用将会出错,效果等同于free(p);

情况五:当原来的指针为NULL

这种情况,的作用就相当于直接调用malloc函数一样;可以这样理解,NULL说明原空间没有分配成功,那么调用realloc函数,肯定需要分配一块新的内存空间,这不就相当于直接调用了malloc函数。

情况六:如果realloc函数调用失败

那么原来的空间地址不会被释放,保留原来的内存,该内存空间可以正常使用。


综上,在使用malloc函数时,需要注意几点:1)调用malloc函数后,需要判断内存是否分配成功;2)使用空间之前,需要给空间赋初始值;3)防止内存越界访问;4)释放内存空间之后free(p);,需要将原指针的值赋空(p=null;),以防再次使用产生错误,出现野指针;5)realloc函数对于原始的内存空间,在分配内存时已经做过处理,因此除realloc函数调用失败外,其余情况不能再次释放原空间内存,否则会出错。


2、既然malloc和free已经可以分配内存了,为什么还要引入new和delete?

首先需要明白,malloc和free是c语言中的c库函数,而new和delete是c++中的标识符;因此这两组拥有不同的性质;

接着,malloc和free不仅可以使用在C语言中,也可以使用在c++语言中,但是new和delete只是c++中特有的属性,在C语言中无法使用,因此new和delete有他的局限性;

再次,new和delete不仅需要分配内存空间,而且在面向对象的语言中,对于对象,还需要完成初始化,触发对象的构造和析构,这些操作是malloc和free无法完成的(笔者就在曾经实现链表的过程中,在结构体定义时,将一个数组元素定义为string类型的,在使用malloc申请内存后,调用过程中无法给该元素赋值。从这个例子中可以看出虽然malloc和new分配的内存大小相等,但是具体的内存内部工作还是有区别的)。

最后,malloc在分配内存时,需要开发者手动的指定元素的大小,并且返回值需要显式的类型转化;但是new就不需要指定和转化。


3、在c++中,既然new和delete可以完成所有分配的工作,为什么还要保留malloc和free?

这是因为c++编译器为了兼容c编译,是c中的所有函数可以在c++编译器上正常使用,因此保留了malloc和free

 
 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数组内存分配概念 的相关文章

  • c++中vector的用法详解

    vector 向量 C 43 43 中的一种数据结构 确切的说是一个类 它相当于一个动态的数组 当程序员无法知道自己需要的数组的规模多大时 用其来解决问题可以达到最大节约空间的目的 用法 1 文件包含 首先在程序开头处加上 include
  • C++中extern关键字的作用

    1 基本解释 xff1a extern可以置于变量或者函数 前 xff0c 以标示变量或者函数的定义在别的文件中 xff0c 提示编译器遇到此变量和函数时在其他模块中寻找其定义 此外extern也可用来进行链接指定 也就是说extern有两
  • 双缓冲技术绘图原理及简单的VC实现

    为了增加自己对双缓冲绘图技术的理解 xff0c 简要做个笔记 xff08 以Windows为例 xff09 xff1a 1 Windows 绘图原理 我们在 Windows 环境下看到各种元素 xff0c 如菜单 按钮 窗口 图像 xff0
  • C#中Tuple的使用

    定义 xff1a 元组是具有 特定数量和序列 的元素 的数据结构 xff08 注意断句哈 xff01 xff09 元组通常有四种使用方式 一 表示一组数据 例如 xff0c 一个元组可以表示一条数据库记录 xff0c 并且每一个分量对应表示
  • 调用C++dll

    1 dll 的优点 代码复用是提高软件开发效率的重要途径 一般而言 xff0c 只要某部分代码具有通用性 xff0c 就可将它构造成相对独立的功能模块并在之后的项目中重复使用 比较常见的例子是各种应用程序框架 xff0c ATL MFC 等
  • DLL程序入口DllMain详解

    DLL程序入口点函数 xff1a DllMain xff0c 注意 xff1a 大小写是区别的 仅导出资源的DLL可以没有DllMain函数 函数原型 cpp view plain copy print BOOL APIENTRY DllM
  • C++编写DLL的方法

    在写C 43 43 程序时 xff0c 时常需要将一个class写成DLL xff0c 供客户端程序调用 这样的DLL可以导出整个class 也可以导出这个class的某个方法 一 导出整个class 方法很简单 xff0c 只需要在类的头
  • dll文件的c++制作

    1 首先用vs2005建立一个 c 43 43 的dll 动态 链接 库 文件 xff0c 这时 xff0c DllTest cpp 定义 DLL 应用程序的入口点 include 34 stdafx h 34 include 34 Dll
  • vs2008 C++创建和调用标准DLL

    为了共享代码 xff0c 需要生成标准的dll xff0c 本文将介绍在vs2008 C 43 43 生成及调用dll 一 生成DLL 生成一个名为FunDll的dll文件 xff0c 对外函数为addl step1 vs2008 环境下
  • VSCode使用SSH免密登录服务器

    VSCode使用SSH免密登录服务器 前言一 SSH连接服务器1 1 安装ssh插件1 2 配置连接 二 免密登录服务器2 1 生成公钥2 2 服务器新建授权文件2 3 本地复制公钥到服务器 总结 前言 vscode使用remote ssh
  • 使用directX 7结合C#进行2D游戏编程

    使用directX 7结合C xff03 进行2D游戏编程 前言 对于C 的开发人员来讲 xff0c GDI 43 是一个拥有丰富的绘图API指令 传统 高效的程序集 但不幸的是 xff0c 你要想用她来开发一个复杂而又平滑的动画的时候 x
  • DirectX学习笔记_关于Sprite.Draw2D的说明

    在DirectX的Sprite中提供一个Draw2D的方法 xff0c 该方法绘制一个 Sprite 对象用于二维空间中显示 xff0c 在DirectX 9 0C中 xff0c 该方法有6个重载 xff0c 分别是 1 public vo
  • 关于Direct2D

    关于Direct2D Direct2D是一个硬件加速的 xff0c 提供立即模式的二维图形API 它提供了二维的几何体 xff0c 位图 xff0c 文本的高性能 xff0c 高质量的渲染 十分方便的是 xff0c Direct2D与GDI
  • C# GDI+ 绘图

    1 坐标系统 1 坐标原点 xff1a 在窗体或控件的左上角 xff0c 坐标为 0 0 2 正方向 xff1a X轴正方向为水平向右 xff0c Y轴正方向为竖直向下 3 单位 xff1a 在设置时 xff0c 一般以像素为单位 xff0
  • lock锁和monitor.enter锁

    210 08 05 14 50 28 转载 Lock object 锁的使用 using System using System Threading namespace program class wangjun public static
  • windows重绘机制原理

    一 Windows程序中的绘制和更新 与DOS环境比较 xff0c Windows中的应用程序在处理文字和图形绘制时有以下区别 xff1a 1 只能在窗口的客户区域绘制文字和图形 2 在窗口上绘制的内容不一定能够保留到程序下一次有意地改写时
  • C# Winform 出现异常:无法将顶级控件添加到控件,解决方案如下:

    Form1Test frm 61 new Form1Test frm TopLevel 61 false 重要的一个步骤 frm Parent 61 splitContainerPanel Panel2 frm Show
  • c#中的Form.Show和Form.ShowDialog的区别

    出处 xff1a http hi baidu com cysteine blog item 01e32224702ff5398744f9bf html 区别1 xff1a ShowDialog是模态的 xff08 独占用户输入 xff09
  • 浅析C#中foreach引用变量

    昨天做老师的网站作业 要对一些对象做添加修改删除处理 别的倒没什么 xff0c 删除时出现了点问题似的 因为是从一个类的集合中删除掉一个元素 这样就要遍历整个集合 xff0c 而foreach正是为遍历准备的新玩意 自然而然用上了 于是代码

随机推荐

  • 用汇编的眼光看C++(之拷贝、赋值函数)

    拷贝构造函数和复制函数是类里面比较重要的两个函数 两者有什么区别呢 xff1f 其实也很简单 xff0c 我们可以举个例子 xff0c 加入有这样一个类的定义 xff1a cpp view plain copy class apple pu
  • IDEA配置一个入门的ssh事例,解决Artifact war exploded:Error during artifact deployment. See server log for detail

    首先 xff0c 我的版本ideaIU 2017 3 4 xff0c 一 新建一个项目project 1 1 create new project 2 file new project 2 这里选择spring xff0c struts2
  • WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 C

    WinForm 之Control Invoke 和Control BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用 但可以通过 invoke 来保证 Control 线程安全 在跨线程更新的时候
  • C#中跨线程访问控件问题解决方案

    net 原则上禁止跨线程访问控件 xff0c 因为这样可能造成错误的发生 xff0c 推荐的解决方法是采用代理 用代理方法来间接操作不是同一线程创建的控件 第二种方法是禁止编译器对跨线程访问作检查 xff0c 可以实现访问 xff0c 但是
  • C#中Invoke的用法(转)

    转载 转自 xff1a http blog 3snews net html 30 34530 27563 html 在多线程编程中 xff0c 我们经常要在工作线程中去更新界面显示 xff0c 而在多线程中直接调用界面控件的方法是错误的做法
  • 【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang)

    今天无意中看到有关Invoke和BeginInvoke的一些资料 xff0c 不太清楚它们之间的区别 所以花了点时间研究了下 据msdn中介绍 xff0c 它们最大的区别就是BeginInvoke属于异步执行的 Control Invoke
  • C#中Invoke 和 BeginInvoke的涵义和区别

    BeginInvoke 方法真的是新开一个线程进行异步调用吗 xff1f 参考以下代码 xff1a public delegate void treeinvoke private void UpdateTreeView MessageBox
  • C# 理解lock

    一 为什么要lock xff0c lock了什么 xff1f 当我们使用 线程 的时候 xff0c 效率最高的方式当然是 异步 xff0c 即各个线程同时运行 xff0c 其间不相互依赖和等待 但当不同的线程都需要访问某个资源的时候 xff
  • excel操作的几种方法

    using System using System Collections Generic using System Text using System Data using System Windows Forms using Syste
  • c#中如何实现拷贝对象

    大家都知道 xff0c 在C 中变量的存储分为值类型和引用类型两种 xff0c 而值类型和引用类型在数值变化是产生的后果是不一样的 xff0c 值类型我们可以轻松实现数值的拷贝 xff0c 那么引用类型呢 xff0c 在对象拷贝上存在着一定
  • 深入了解Windows句柄到底是什么

    总是有新入门的Windows程序员问我Windows的句柄到底是什么 xff0c 我说你把它看做一种类似指针的标识就行了 xff0c 但是显然这一答案不能让他们满意 xff0c 然后我说去问问度娘吧 xff0c 他们说不行网上的说法太多还难
  • 句柄概念

    句柄 xff08 handle xff09 xff0c 有多种意义 xff0c 其中第一种是指程序设计 xff0c 第二种是指Windows编程 现在大部分都是指程序设计 程序开发这类 第一种解释 xff1a 句柄是一种特殊的 智能指针 当
  • 腾讯云大数据发布最新产品矩阵,助力企业整合打通海量数据

    9月11日 xff0c 主题为 释放数字经济发展的新动能 的腾讯全球数字生态大会大数据专场在线上拉开帷幕 腾讯大数据领域的多位顶级专家 xff0c 与包括 Hadoop 创始人 Doug Cutting 在内的业内顶级大咖 xff0c 以及
  • C/C++中函数参数传递

    看了内存管理的有关内容 xff0c 有一点了解 xff0c 但不是很深入 xff0c 发现之前写代码时有很多细节问题没有注意到 xff0c 只知道这样做可以实现功能 xff0c 却不知道为什么可以这样 xff0c 对于采用自己的方法造成的隐
  • Windows窗口刷新机制详解

    1 Windows的窗口刷新管理 窗口句柄 xff08 HWND xff09 都是由操作系统内核管理的 xff0c 系统内部有一个z order序列 xff0c 记录着当前窗口从屏幕底部 xff08 假象的从屏幕到眼睛的方向 xff09 x
  • C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)

    BSS段 xff08 bss segment xff09 通常是指用来存放程序中 未初始化 的 全局变量 的一块内存区域 BSS是英文Block Started by Symbol的简称 BSS段属于静态内存分配 数据段 xff1a 数据段
  • C# 窗体Show和ShowDialog 方法的区别详解

    CenterParent 窗体在其父窗体中居中 CenterScreen 窗体在当前显示窗口中居中 xff0c 其尺寸在窗体大小中指定 Manual 窗体的位置由 Location 属性确定 WindowsDefaultBounds 窗体定
  • c# 窗口句柄问题 。

    1 如何获得一个窗口的句柄 xff1f 例如获取窗口PictureBox控件 xff08 其他控件也可以 xff09 的句柄 xff0c csharp view plain copy IntPtr handle 61 pictureBox
  • c#中已知一个外部窗口的句柄,怎么关闭

    已知一个外部窗口的句柄 xff0c 怎么关闭它 怎么给这个窗口的一个文本框设置内容 public void Test Handle windowhandle string TextBoxName System windws froms fr
  • 数组内存分配概念

    在这里解答一下 xff1a int arr 4 amp arr 1 61 arr 0 43 sizeof int 静态分配 xff0c 即普通数组 xff0c 由于在栈中分配 xff0c 而栈的生成方向是自高地址向低地址生成 所以有 xff