作业━━第 7 章(1)━━动态内存分配
- 格式:doc
- 大小:171.50 KB
- 文档页数:10
实验报告实验课程名称:动态内存分配算法年12月1日实验报告一、实验内容与要求动态分区分配又称为可变分区分配,它是根据进程的实际需要,动态地为之分配内存空间。
在实验中运用了三种基于顺序搜索的动态分区分配算法,分别是1.首次适应算法2.循环首次适应算法3.最佳适应法3.最坏适应法分配主存空间。
二、需求分析本次实验通过C语言进行编程并调试、运行,显示出动态分区的分配方式,直观的展示了首次适应算法循环首次适应算法、最佳适应算法和最坏适应算法对内存的释放和回收方式之间的区别。
首次适应算法要求空闲分区链以地址递增的次序链接,在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区为止,然后在按照作业的大小,从该分区中划出一块内存空间,分配给请求者,余下的空余分区仍留在空链中。
优点:优先利用内存中低址部分的空闲分区,从而保留了高址部分的大空闲区,为以后到达的大作业分配大的内存空间创造了条件。
缺点:低址部分不断被划分,会留下许多难以利用的、很小的空闲分区即碎片。
而每次查找又都是从低址部分开始的,这无疑又会增加查找可用空闲分区时的开循环首次适应算法在为进程分配内存空间时,不是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直到找到一个能满足要求的空闲分区。
优点:该算法能使内存中的空闲分区分布得更均匀,从而减少了查找空闲分区时的开销。
最佳适应算法该算法总是把能满足要求、又是最小的空闲分区分配给作业,避免大材小用,该算法要求将所有的空闲分区按其容量以从小到大的顺序形成一空闲分区链。
缺点:每次分配后所切割下来的剩余部分总是最小的,这样,在存储器中会留下许多难以利用的碎片。
最坏适应算法最坏适应算法选择空闲分区的策略正好与最佳适应算法相反:它在扫描整个空闲分区或链表时,总会挑选一个最大的空闲区,从中切割一部分存储空间给作业使用。
该算法要求,将所有的空闲分区,按其容量以大到小的顺序形成一空闲分区链。
150 C语言程序设计教程由于所有命令行参数都被当做字符串来处理,所以在这里字符指针数组argv的各个元素依次指向命令行中的参数,如图6-29所示。
图6-29 命令行参数示意图命令行参数很有用,尤其是在批处理命令中使用较为广泛。
例如,可通过命令行参数向一个程序传递这个程序所要处理的文件的文件名,还可用来指定命令的选项等。
当程序不需要命令行参数时,一般就将main( )函数定义为无参数。
6.7 动态内存分配在实际应用中,程序运行中的很多存储要求事先无法确定,需要根据运行时的实际存储需求分配适当的存储区,用于存放那些在运行时才能确定数量的数据。
C语言标准函数库中提供了一对标准函数malloc( )函数和free( )函数,用于动态申请和释放内存空间。
它们的原型被声明在stdlib.h中,所以在调用时,需要利用编译预处理命令#include将stdlib.h包含到程序中。
1.动态内存分配函数malloc( )malloc( )函数原型为:void *malloc(unsigned int size);malloc( )函数的功能是请求系统分配size个字节的连续内存空间。
如果分配成功,将返回一个指向该内存空间首地址的指针;若系统不能提供足够的内存单元,函数将返回空指针NULL。
由于该函数可以为各种类型的数据申请存储空间,其返回值类型是空类型的指针(void *),所以要想将返回值赋给某一具体类型的指针变量,必须进行强制类型转换。
例如:int *pi;pi=(int *)malloc(4);其中,malloc(4)表示申请4个字节的内存空间,并将malloc(4)返回值的void *类型强制转为int *类型后,再赋给int型指针变量pi,即用int型指针变量pi指向这段存储空间的首地址。
若不能确定某种类型所占内存的字节数,则需使用sizeof( )计算本系统中该类型所占内存的字节数,然后再用malloc( )向系统申请相应字节数的存储空间。
动态内存分配掌握动态内存分配的原理和使用方法动态内存分配是指在程序运行时,根据需要动态地分配内存空间。
相比于静态内存分配,动态内存分配具有灵活性和效率方面的优势。
在程序设计中,正确地掌握动态内存分配的原理和使用方法是非常重要的。
本文将探讨动态内存分配的原理和使用方法,以帮助读者更好地理解并应用于实际开发中。
一、动态内存分配的原理在进行动态内存分配之前,我们首先需要了解几个重要的概念:1. 堆:在程序运行时,动态内存的分配是通过堆来实现的。
堆是一块较大的内存区域,用于存储动态分配的内存。
2. 指针:在动态内存分配过程中,我们通过指针来访问和管理分配的内存。
指针是一个变量,其值是一个地址,指向内存中的某个位置。
3. free store:是动态内存分配的另一种说法,用于表示程序运行时可以动态分配的内存空间。
动态内存分配的原理如下:1. 分配内存:通过调用相关的函数(如malloc、new等),向操作系统申请一块指定大小的内存空间。
2. 绑定指针:将申请到的内存空间的地址与一个指针绑定,以便后续使用。
3. 使用内存:通过指针对动态分配的内存空间进行读取和写入操作。
4. 释放内存:在使用完动态分配的内存后,需要手动释放内存,以便其他程序可以继续使用该内存。
以上就是动态内存分配的基本原理,了解这些原理对于正确和高效地使用动态内存非常重要。
二、动态内存分配的使用方法下面将介绍几种常见的动态内存分配的使用方法,以帮助读者更好地掌握动态内存的使用。
1. 使用malloc/free函数malloc和free是C语言中常用的动态内存分配函数。
malloc函数用于分配一块指定大小的内存空间,free函数用于释放之前分配的内存空间。
示例代码如下:```c#include <stdlib.h>int main(){int* p = (int*)malloc(sizeof(int)); // 分配4个字节大小的内存空间if(p != NULL){*p = 10; // 对动态分配的内存进行写入操作printf("%d\n", *p); // 读取动态分配的内存free(p); // 释放内存空间}return 0;}```2. 使用new/delete运算符在C++中,可以使用new和delete运算符来进行动态内存分配和释放操作。
动态内存的分配 在声明数组的时候,我们需要考虑数组应该有多⼤?在很多的情况下,我们并不清楚要定义的这个数组到底有多⼤,此时我们就要把数组定义得⾜够⼤。
这样程序在运⾏时就申请了固定⼤⼩的⾜够⼤的内存空间。
但是如果程序需要的元素⽐较少时,内存空间就被浪费掉了。
少数情况下我们定义的数组不够⼤,这时候就可能引起下标越界错误。
这是时候可以⽤动态内存分配就可以解决上⾯的问题. 所谓动态内存分配就是指在程序执⾏的过程中动态地分配或者回收存储空间的分配内存的⽅法。
动态内存分配不象数组等静态内存分配⽅法那样需要预先分配存储空间,⽽是由系统根据程序的需要即时分配,且分配的⼤⼩就是程序要求的⼤⼩。
C函数库提供了两个函数,malloc 和 free,分别⽤于执⾏动态内存分配和释放。
原型如下所⽰: void *malloc( size_t size); void free( void *pointer); malloc的参数就是需要分配的内存字节(字符)数。
若内存池中可⽤内存可以满⾜需求,malloc就返回⼀个指向被分配的内存块起始位置的指针,当可⽤内存⽆法满⾜要求时就会返回⼀个NULL指针。
因此每个从malloc返回的指针都要检查确保它⾮NULL。
free的参数必须要么是NULL,要么是⼀个先前从malloc、calloc或realloc返回的值。
另外还有两个内存分配函数,calloc 和 realloc。
原型如下所⽰: void *calloc( size_t num_elements, size_t element_size); void realloc( void *ptr, size_t new_size); calloc也⽤于分配内存。
它在返回指向内存的指针前把它初始化为0。
realloc函数⽤于修改⼀个原先已经分配的内存块的⼤⼩。
如果扩⼤内存块,原来的内容保留,新加的添到原先的后⾯。
如果缩⼩内存块,该内存尾部的部分内存被拿掉,剩余部分原先内容依然保留。
C语言中的动态内存分配详解
C语言中的动态内存分配允许程序员在运行时根据需要分配或释放内存。
这在处理可变大小的数据结构或处理大量数据时非常有用。
C语言提供了三个函数来支持动态内存分配:malloc(), calloc() 和 free()。
1.malloc()
malloc() 函数用于分配指定大小的内存。
它返回一个指向分配的内存的指针,如果分配失败,则返回 NULL。
在上面的代码中,我们使用 malloc() 函数分配了一个整数的内存空间,并将返回的指针存储在 ptr 变量中。
2.calloc()
calloc() 函数用于分配指定数量和大小的内存。
它返回一个指向分配的内存的指针,如果分配失败,则返回 NULL。
在上面的代码中,我们使用 calloc() 函数分配了10个整数的内存空间,并将返回的指针存储在 ptr 变量中。
3.free()
free() 函数用于释放之前通过 malloc() 或 calloc() 分配的内存。
在上面的代码中,我们首先使用 malloc() 函数分配了一个整数的内存空间,然后使用 free() 函数释放了该内存空间。
需要注意的是,动态内存分配的内存是在堆上分配的,而不是在栈上。
这意味着您需要手动管理这些内存,以避免内存泄漏或悬挂指针等问题。
C语⾔中关于动态内存分配的详解⽬录⼀、malloc 与free函数⼆、calloc三、realloc四、常见的动态内存的错误【C语⾔】动态内存分配本期,我们将讲解malloc、calloc、realloc以及free函数。
这是个动态内存分配函数的头⽂件都是 <stdlib.h>。
c语⾔中动态分配内存的函数,可能有些初学c语⾔的⼈不免要问了:我们为什么要通过函数来实现动态分配内存呢?⾸先让我们熟悉⼀下计算机的内存吧!在计算机的系统中⼤致有这四个内存区域:1)栈:在栈⾥⾯储存⼀些我们定义的局部变量以及形参(形式参数);2)字符常量区:主要是储存⼀些字符常量,⽐如:char *p=”hello world”;其中”hello world”就储存在字符常量区⾥⾯;3)全局区:在全局区⾥储存⼀些全局变量和静态变量;堆:堆主要是通过动态分配的储存空间,也就是我们接下需要讲的动态分配内存空间。
静态内存和动态内存的⽐较:静态内存是有系统⾃动分配,由系统⾃动释放。
静态内存是在栈分配的。
(例如:函数⾥的局部变量)动态内存是由程序员⼿动分配,⼿动释放。
动态内存是在堆分配的。
(例如:⽤C语⾔写链表时,需要⾃⼰对Node结点分配内存空间)⼀、malloc 与free函数void* **malloc( size_t ** size);返回类型: void*,也就是说这个函数的可以返回所有类型的指针形式。
只需要在开辟空间的时候进⾏强制类型转换⼀下即可。
函数参数:size_t size, 这个参数就是告诉这个函数,你需要开辟多少个字节的内存空间。
void free(void* memblock) ;没有返回参数。
函数参数:void* memblock, free函数可以接收来⾃所有类型指针的动态分配的内存空间。
⼀切以栗⼦来描述吧:#include <stdlib.h>#include <stdio.h>int main(){//开辟10个int类型的空间int* arr = (int*)malloc(10 * sizeof(int)); //切记这⾥给的⼤⼩,是10 * int(4个字节)int i = 0;if (arr == NULL){perror("malloc"); //有可能,malloc开辟空间失败,则malloc会返回NULLreturn 1;}for (i = 0; i < 10; i++)*(arr + i) = i; //放⼊数据 0 (9)for (i = 0; i < 10; i++)printf("%d ",*(arr + i));//记得释放所开辟的空间free(arr);return 0;}⼆、callocvoid* calloc (size_t num, size_t** size );返回类型:与malloc函数是⼀样的,就不在多说了。
动态内存分配【学习要点】1.掌握C++的四个内存区域。
2.掌握堆内存和动态存储分配。
3.掌握new 与delete 运算符的使用。
4.掌握动态创建对象。
5.掌握对象的浅拷贝、浅赋值。
6.掌握对象的深拷贝、深赋值。
------------------------------------------------------------------------------------------------------------------------------------------------【例题分析】1.为指针变量p赋初值,下列语句中不正确的是______。
A.int *p = 0;B.float *p = ( float* )50;C.int *p = new 50;D.float *p = new float[ 50 ];【答案】C【解析】答案A给指针p 赋0值(空指针)是正确的;答案B将整数50的单元类型强制转换为实型指针也是可以的;答案D将指针p 指向在堆区上申请的具有50个元素的实型数组也是可以的;答案C错误,因为new 运算符的运算对象不能是常数。
2.编写程序:有数组a,其中存放20个数据为:{ 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 8, 8, 9, 10, 10 },已按升序排列。
试定义一个类ARRAY,实现将数组中相同的元素删除成只剩一个,即删除重复的数据。
删除重复的数据后,数组a中的内容为:{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }。
要求:①私有成员数据:●int *a;//存放数据的动态数组容器的起始地址●int n;//动态数组容器中已存放数据的个数②公有成员函数:●ARRAY ( int x[ ] , int size );//用数组x[size] 来初始化ARRAY类的对象●~ARRAY ( );//析构函数●void deleteSame ( );//将数组中重复的元素删除成只剩一个●void show ( );//按每行4个数据的格式输出③编写main()函数对ARRAY类进行测试。
【答案】编写程序如下:#include<iostream.h>class ARRAY{int *a;int n;public:ARRAY ( int x[ ] , int size ){ a = new int [ size ];n = size ;for ( int i=0; i<n; i++ ) a[ i ] = x[ i ]; }~ARRAY ( ) {delete [ ] a; }void deleteSame ( ){for ( int i=0, j=0; j<n; j++ ){ while ( a[ i ] == a[ j ] && j<n ) j++;if ( j<n ) { a[ ++i ] = a[ j ]; } }n = ++i ; }void show ( ){for ( int i=0; i<n; i++ ){ cout << a[ i ] << '\t';if ( (i+1)%4==0 ) cout << endl; }cout << endl; }};void main( ){int a[ 20 ] = { 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 8, 8, 9, 10, 10 };ARRAY arr( a, 20 );arr.deleteSame( );arr.show( ); }3.编写程序:有一个线性数列,共有size个元素,要求从指定下标m开始的n个元素进行降序排列。
例如,原数列的10个元素排列为:{ 2,8,4,0,3,9,5,7,9,8 },若要求从第3个元素开始的5个数据降序排列,则得到的新数列为:{ 2,8,4,9,7,5,3,0,9,8 }。
试定义一个List类,实现上述功能。
要求:①私有成员数据:●int *arr;//存放动态数组容器空间的起始地址●int size;//动态数组容器中已存放元素的个数②公有成员函数:●List ( int a[ ] , int len );//用数组a[ len ] 来初始化List类对象●~ List ( );//析构函数●void sortPart ( int m, int n );//将数列从第m个元素开始的n个数据降序排列●v oid print ( );//输出数列③编写main()函数对List类进行测试。
【答案】编写程序如下:#include<iostream.h>class List{int *arr;int size;public:List ( int a[ ], int len ){ size = len;arr = new int [ size ];for ( int i=0; i<size; i++ ) arr[ i ] = a[ i ]; }~List ( ) {delete [ ] arr; }void sortPart ( int m, int n ){int i, j, temp;for ( i=m; i<m+n-1; i++ )for ( j=i+1; j<m+n; j++)if ( arr[ i ]<arr[ j ] ) { temp = arr[ i ];arr[ i ] = arr[ j ];arr[ j ] = temp; } }void print( ){for ( int i=0; i<size; i++ ) cout << arr[ i ] << “”;cout << endl; }};void main(){int a[10] = { 2, 8, 4, 0, 3, 9, 5, 7, 9, 8 };List list ( a, 10 );list.sortPart( 3, 5 );list.print(); }------------------------------------------------------------------------------------------------------------------------------------------------【思考题】㈠选择题1.设语句int *p=new int ______;选择正确的填空使p所指向的内存空间赋初值56。
A.[ 56 ]B.( 56 )C.{ 56 }D.= 56【答案】???B2.下面有关内存分配的说法中,错误的是______。
A.指针变量可以保存动态分配存储空间的地址。
B.用运算符new 为指针变量分配的存储空间在堆区。
C.数据元素存储在堆区的数组在建立时可同时初始化。
D.指向静态变量的指针不必用delete 释放。
【答案】???D3.为指针变量赋值,下列语句中不正确的是______。
A.int *p = 0;B.float *p = ( float * ) 50;C.int *p = new int [ 2 ] [ 3 ];D.float *p = new float ( 50 );【答案】???C------------------------------------------------------------------------------------------------------------------------------------------------㈡完善程序题1.在顺序表类Line中,其构造函数Line( int a[ ], int n )是用长度为n的数组初始化Line类的对象,成员函数sort() 是实现升序排序的函数,请完善程序。
#include<iostream.h>class Line{ int *num;int count;public:Line ( ) {num = 0; count = 0; }Line ( int a[ ], int n ){count = n;num =①;for ( int i=0; i<count; i++ ) ②;}void sort ( ){int i, j, k;for ( i=0; i<count-1; i++ )for ( j=i+1; j<count; j++ )if ( ③){ k= num [ i ]; num [ i ]= num [ j ]; num [ j ] = k; } }~Line() {if ( num ) ④;}void print(){ for ( int i=0; i<count; i++ ) cout << num [ i ] << “”;cout << endl; }};void main( ){ int a[10] = { 5, 2, 8, 6, 1, 3, 9, 10, 4, 7 };Line line ( a, 10 ); line.print();line.sort(); line.print(); }【答案】①???a【答案】②???num[i]=a[i]【答案】③???num[i]>num[j]【答案】④???delete []num2.在类String中,重载“+=”运算符实现String类的复合赋值运算,请完善程序。
# include <iostream.h># include <①>class String{char *str;public:String ( char *s=0 ){ if ( s==0 ) str = 0;else { str = new char [ strlen(s)+1 ];strcpy ( str, s ); } }String ( String &s ){if ( s.str ) { str = ②];strcpy ( str, s.str ); }else str = 0; }~String ( ) {③;}String & operator+= ( String & );void show() {if ( str ) cout << str << '\n'; }};④operator+= ( String &s ){ if ( s.str != 0 ){ char *p = str;if ( p ) { str = new char [ ⑤];strcpy ( str, p );strcat ( str, s.str );delete ⑥;}else { str = new char [ strlen( s.str )+1 ];strcpy( str, s.str ); } }return ⑦;}void main ( ){String s1( "I am a " ), s2( "Student." );String s3( s1 ) , s4;s3 += s2;s4 += s2;s1.show(); s2.show(); s3.show(); s4.show(); }【答案】①???string.h【答案】②???new char[strlen(s.str)+1]【答案】③???delete []str【答案】④???&String【答案】⑤???strlen(s.str)+strlen(p)+1【答案】⑥???p【答案】⑦???*this3.在线性表类SLIST中,成员函数inelem()的功能:将新元素data按顺序放入线性表中。