C++第七章 动态内存分配习题解答
c语言的动态内存分配题目
以下是一个使用C语言动态内存分配的题目示例:
题目:给定一个长度为n的整数数组,要求将其划分为若干个长度为k的连续子数组,使得所有子数组的和尽可能接近。
请你实现一个函数,返回划分后的所有子数组的最大和。
示例输入:
输入:n = 5, k = 2
输出:8
解释:将数组[1, 2, 3, 4, 5] 划分为[1, 2], [3, 4], [5] 三个子数组,它们的和分别为3, 7, 5,和为15,接近于最大和。
实现这个函数可以使用动态规划的思想。
首先定义一个长度为n的数组dp,其中dp[i]表示以第i个元素结尾的子数组的最大和。
然后从左到右遍历数组,对于每个位置i,计算dp[i]的值。
如果i-1位置的子数组和大于0,则将dp[i]设置为dp[i-1]加上当前元素的值;否则,将dp[i]设置为当前元素的值。
最后返回dp[n-1]即可。
C语言程序设计教程 第七章 课后习题参考答案
{
for(j=0;j<N;j++)
{
printf("%4d",a[i][j]);
}
printf("\n");
}
for(i=0;i<M;iபைடு நூலகம்+)
{
for(j=0;j<N;j++)
{
if(i==j)
m+=a[i][j];
}
}
printf("主对角线元素之和为:%d\n",m);
批注本地保存成功开通会员云端永久保存去开通
P198 3求主、副对角线元素之和
#include<stdio.h>
#define M 4
#define N 4
int main()
{
int a[M][N]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int i,j,m=0,n=0;
{
if(a[j]>a[j+1])
{
tmp=a[j];
a[j]=a[j+1];
a[j+1]=tmp;
}
}
}
printf("\n");
printf("排序后的数组为:\n");
for(i=0;i<N;i++)
{
printf("%4d",a[i]);
}
}
P76 3成绩
#include<stdio.h>
void input(int cla[50][3],int n);
《C语言程序设计教程》第三版课后习题参考答案
《C语言程序设计教程》第三版课后习题参考答案C语言程序设计教程第三版课后习题参考答案第一章:C语言概述1.1 C语言的特点答案:C语言是一种通用的、面向过程的程序设计语言,具有高效、简洁、灵活等特点。
它提供了丰富的程序设计元素和功能,适用于各种不同的应用领域。
1.2 C语言程序的基本结构答案:C语言程序由预处理指令、函数声明、函数定义、变量声明和语句组成。
其中,预处理指令用来引入头文件或定义宏,函数声明用来声明函数的名称和参数,函数定义用来实现函数的功能,变量声明用来声明变量的类型和名称,语句用来表达具体的计算过程。
1.3 C语言的数据类型答案:C语言提供了多种数据类型,包括基本类型(整型、浮点型、字符型等)和派生类型(数组、指针、结构体等)。
每种数据类型在内存中占据一定的存储空间,并具有特定的取值范围和操作规则。
1.4 C语言的运算符和表达式答案:C语言支持各种运算符和表达式,例如算术运算符(+、-、*、/等)、关系运算符(>、<、==等)、逻辑运算符(&&、||、!等)等。
通过运算符和表达式可以进行各种数值计算和逻辑判断。
第二章:基本数据类型与运算2.1 整型数据类型答案:C语言提供了不同长度的整型数据类型,包括有符号整型(int、long等)和无符号整型(unsigned int、unsigned long等)。
整型数据类型可以表示整数值,并具有不同的取值范围。
2.2 浮点型数据类型答案:C语言提供了浮点型数据类型(float、double等),用来表示带小数部分的实数值。
浮点型数据可以表示较大或较小的数值,并具有一定的精度。
2.3 字符型数据类型答案:C语言提供了字符型数据类型(char),用来表示单个字符。
字符型数据可以用于表示各种字符(包括字母、数字、符号等)。
2.4 布尔型数据类型答案:C语言不直接支持布尔型数据类型,但可以使用整型数据类型来表示布尔值(0表示假、非零表示真)。
《动态分配内存与数据结构》课后习题(含答案)
6、分析下列代码是否存在问题,选择合适的选项: int main(void) { int *p = new int [10]; p = new int [10]; delete [] p; p = NULL; return 0; } A.没有问题 C.存在空悬指针
B.有内存泄漏 D.存在重复释放同一空间 D 。 D.堆区
3、写出程序的运行结果 #include <iostream> #include <string> using namespace std; template <typename T> class Node { public: T data; Node<T> *link; Node(const T&info) {data=info;link=NULL;} }; template <typename T> class OrderedLink { Node<T> *head; public: OrderedLink() {head=NULL;} OrderedLink(const T*list,int num) { head = NULL;
B. p->next=r; q->next=r->next; r->next=q; C. q->next=r->next; r->next=q; p->next=r; D. r->next=q; p->next=r; q->next=r->next; 二、填空题 1、在长度为 10 的顺序存储的线性表中插入一个元素,最坏情况下需要移动表 中 10 个元素。
2、 设某循环队列的容量为 40, 头指针 front=3 (指向队头元素的前一位置) , 尾指针 rear=25 (指向队尾元素),则该循环队列中共有 22 个元素。
C语言内存分配问题(整理)
我查了下资料,有说分四个,有说分五个加一个程序代码区,我没查到参考的专业书籍。所 以麻烦知道的告知一下,完善一下。
2、 内存分配方式 内存分配方式有三种:
1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整 个运行期间都存在。例如全局变量,static 变量。
4、动态分配释放内存举例 用 malloc 动态分配内存后一定要判断一下分配是否成功,判断指针的值是否为 NULL。 内存分配成功后要对内存单元进行初始化。 内存分配成功且初始化后使用时别越界了。 内存使用完后要用 free(p)释放,注意,释放后,p 的值是不会变的,仍然是一个地址值, 仍然指向那块内存区,只是这块内存区的值变成垃圾了。为了防止后面继续使用这块内存, 应在 free(p)后,立即 p=NULL,这样后面如果要使用,判断 p 是否为 NULL 时就会判断出 来。
NO.2
char *GetMemory(void) {
char Байду номын сангаас[] = hello world; retrun p; } void Test(void) { char *str = NULL; str = GetMemory(); printf(str); }
问题同 NO.1
NO.3
void GetMemory(char **p, int num) {
free(str); if(str != NULL) {
strcpy(str,"world"); printf(str); } }
问题同 NO.1 我对以上问题的分析:
NO.1:程序首先申请一个 char 类型的指针 str,并把 str 指向 NULL(即 str 里存的是 NULL 的地址,*str 为 NULL 中的值为0),调用函数的过程中做了如下动作: 1、申请一个 char 类型的指针 p, 2、把 str 的内容 copy 到了 p 里(这是参数传递过程中系统所做的), 3、为 p 指针申请了 100 个空间, 4、返回 Test 函数.最后程序把字符串 hello world 拷贝到 str 指向的内存空间里.到这里错 误出现了! str 的空间始终为 NULL 而并没有实际的空间.深刻理解函数调用的第 2 步,将不难发现问 题所在!(注意:传递的参数和消除的参数) NO.2:程序首先申请一个 char 类型的指针 str,并把 str 指向 NULL.调用函数的过程中做了 如下动作: 1申请一数组 p[]并将其赋值为 hello world(数组的空间大小为 12), 2返回数组名 p 付给 str 指针(即返回了数组的首地址). 那么这样就可以打印出字符串"hello world"了么?当然是不能的! 因为在函数调用的时候漏掉了最后一步.也就是在第2步 return 数组名后,函数调用还要 进行一步操作,也就是释放内存空间.当一个函数被调用结束后它会释放掉它里面所有的变 量所占用的空间.所以数组空间被释放掉了,也就是说 str 所指向的内容将不确定是什么东 西. NO.3:正确答案为可以打印出 hello.但内存泄漏了! 需要用 free()函数进行释放。
7C++动态存储分配
int main() { Vector v1; //空的向量,无元素 Vector v2(5); //有5个元素的向量,每个元素值为0 Vector v3(5,9);//有5个元素的向量,每个元素值为9 v2.print(); v3.print(); v3.at(2) = 88; //等价于v3[2] = 88; v3.print(); cout << "v3[2] = " << v3.at(2) << endl; if(v1.isEmpty()) cout << "向量为空!" << endl; else cout << "向量不为空!" << endl; cout << "length of v2 is : " << v2.length() << endl; Vector v4(v3); v4.print(); return 0; }
基本类型一般不采用动态存储分配
7
2013-12-16
动态存储空间的回收
用new分配的空间一定要用delete回收 具体使用格式: – delete 指针变量名
– delete[] 指针变量名 //用于动态数组的内存回收 delete只能用于回收new所分配的空间 对于一个指针指向的堆对象只能执行一次 delete操作 delete[]忽略括符内的具体数字,无论是几维数 组的空间回收均只用一个括符表示
21
复制构造函数
主要功能 :
– 用一个已知的对象来初始化一个同类对象
具体声明格式: <类名>::<类名> (const <类名>& <对象名>) 复制构造函数只有一个参数,是该类对象的引用 若用户没有显式定义复制构造函数,编译器会自 动生成一个默认的复制构造函数,其功能是把已 知对象的每个数据成员都复制到新定义的对象中
c语言课后复习题答案
c语言课后复习题答案1. 请解释C语言中变量的作用域和生命周期。
在C语言中,变量的作用域指的是变量可以被访问的代码区域。
局部变量的作用域仅限于定义它的函数或代码块内部,而全局变量的作用域是整个程序。
变量的生命周期是指变量从被创建到被销毁的时间。
局部变量的生命周期从定义它的地方开始,到包含它的函数或代码块结束时结束。
全局变量的生命周期从程序开始执行时创建,到程序结束时销毁。
2. 描述C语言中指针和数组的关系。
在C语言中,指针是一种特殊的变量,它存储了另一个变量的内存地址。
数组名可以被看作是一个常量指针,它指向数组的第一个元素的地址。
通过指针运算,可以访问数组的任意元素。
例如,如果有一个数组`int arr[5];`,那么`arr`指向数组的第一个元素,`arr+1`指向第二个元素,以此类推。
3. 说明C语言中结构体和联合体的区别。
结构体(struct)和联合体(union)都是C语言中用于创建复杂数据类型的复合数据类型。
结构体可以包含不同类型的数据成员,并且每个成员都有自己的内存空间。
联合体则是一种特殊的数据类型,它允许在相同的内存位置存储不同的数据类型,但是任何时候只能存储其中一个成员的值。
结构体和联合体的主要区别在于内存的使用方式和数据的存储方式。
4. 列举C语言中常用的输入输出函数。
C语言中常用的输入输出函数包括`printf()`和`scanf()`用于标准输入输出,`getchar()`和`putchar()`用于单个字符的输入输出,以及`fgets()`和`fputs()`用于字符串的输入输出。
此外,还有`fopen()`、`fclose()`、`fread()`和`fwrite()`等用于文件操作的函数。
5. 解释C语言中的递归函数。
递归函数是一种调用自身的函数。
在C语言中,递归函数通常用于解决可以分解为相似子问题的问题,如计算阶乘、进行排序等。
递归函数需要有一个明确的结束条件,以避免无限递归。
编译预处理和动态存储分配及答案
编译预处理和动态存储分配及答案编译预处理和动态存储分配一、选择题(1)有以下程序 main(){ char p[]={'a', 'b', 'c'}, q[]=\ printf(\ %d\\n\ };程序运行后的输出结果是 A)4 4 B)3 3 C)3 4 D)4 3(2)有以下程序# define f(x) (x*x) main(){ int i1, i2;i1=f(8)/f(4) ; i2=f(4+4)/f(2+2) ; printf(\ }程序运行后的输出结果是 A)64, 28 B)4, 4 C)4, 3 D)64, 64(3)有以下程序 main(){ char a[7]=\ i,j; i=sizeof(a); j=strlen(a); printf(\ %d\\n\}程序运行后的输出结果是 A)2 2 B)7 6 C)7 2 D)6 2(4)以下叙述中正确的是 A)预处理命令行必须位于源文件的开头B)在源文件的一行上可以有多条预处理命令 C)宏名必须用大写字母表示 D)宏替换不占用程序的运行时间(5) 有以下程序 main( ){ char a[]=”abcdefg”,b[10]=”abcdefg”;printf(“%d %d\\n”,sizeof(A) ,sizeof(B) ); }执行后输出结果是 A) 7 7 B) 8 8 C) 8 10 D) 10 10(6) 有以下程序#define f(x) x*x main( ) { int i;i=f(4+4)/f(2+2); printf(“%d\\n”,i); }执行后输出结果是 A) 28 B) 22 C) 16 D) 4(7) 有以下程序 #include #define F(X,Y) (X)*(Y) main (){ int a=3, b=4;printf(\}程序运行后的输出结果是 A) 12 B) 15 C) 16 D) 20(8) 有以下程序main(){ char s[]=\printf(\}执行后输出结果是A) 赋初值的字符串有错 B) 6,7 C) 5,6 D) 6,6(9) 有以下程序main(int arge,char *argv[]) { int n,i=0; while(arv[1][i]!='\\0'{ n=fun(); i++;} printf(%d\\n\}int fun(){ static int s=0; s+=1; return s; }假设程序经编译、连接后生成可执行文件exam.exe,若键入以下命令行 exam 123 则运行结果为(10) 有以下程序 main(){ char a[ ]={‘a’,‘b’,‘c’,‘d’, ‘e’, ‘f’, ‘g’,‘h’,‘\\0’};inti=sizeof(a); j=strlen(a); printf(“%d,%d\\b”i,j); }程序运行后的输出结果是 A)9,9 B)8,9 C)1,8 D)9,8(11) 程序中头文件typel.h 的内容是: #define N 5 #define M1 N*3 程序如下:i,j; #define “type1.h” #define M2 N*2 main() { int i;i=M1+M2; printf(“%d\\n”,i); }程序编译后运行的输出结果是: A) 10 B) 20 C) 25 D) 30(12) 有以下程序 #include main() { char *p,*q;p=(char*)malloc(sizeof(char)*20); q=p; scanf(“%s%s”,p,q);printf(“%s%s\\n”,p,q); }若从键盘输入:abc def,则输出结果是: A) def def B) abc def C) abc d D) d d(13) 若指针p已正确定义,要使p指向两个连续的整型动态存储单元,不正确的语句是 A) p=2*(int*)malloc(sizeof(int)); B) p=(int*)malloc(2*sizeof(int)); C) p=(int*)malloc(2*2);D) p=(int*)calloc(2,sizeof(int));(14) 以下程序的输出结果是 main(){ char st[20]= “hello\\0\\t\\\\\\”; printf(%d %d\\n”,strlen(st),sizeof(st)); }A) 9 9 B) 5 20C) 13 20 D) 20 20(15) 以下程序的输出结果是amovep(int p, int (a)[3],int n) { int i, j; for( i=0;i 感谢您的阅读,祝您生活愉快。
c语言第七章课后题
一、第七章习题7(p184-p187),7.1-7.7全做,7.8-7.12中选做两道,要求给出程序执行结果。
7-1 、#include <stdio.h>int Square(int i){return i*i;}int main(){int i=0;i=Square(i);for(; i<3;i++){static int i=1;i+=Square(i);printf("%d,",i);}printf("%d\n",i);return 0;}结果:结果分析:开头定义square()函数功能:计算一个数的平方入口参数:整数x返回值: i*i主函数: i=0; 进入循环:静态变量i=1 ;i=i+square ( 1) =2;输出2;循环变量i=0+1=1;i=1<3成立静态变量i=i+square (2) =2+4=6 ;输出6;循环变量i=i+1=2;I=2<3 成立静态变量( i 保持原值) i=6 ;i=i+square ( 6) =6+36=42 ;输出 42;循环变量i=i+1=3 ;I=3<3 不成立退出循环输出循环变量i=37-2 、#include <stdio.h>int hour,minute,second; /* 定义全局变量 */ voidupdate(){second ++;if(second == 60){second=0;minute++;}if(minute==60){minute=0 ;hour++;}if(hour==24)hour=0;}void display(){printf(" %d : %d : %d\n ",hour,minute,second);}void delay(){int t;for (t=0;t<100000000;t++); /*用循环体为空语句的循环实现延时*/}int main(){int i;second=0;for(i=0;i<1000000;i++){update(); /*利用循环控制时钟运行时间*/display(); /*显示时,分,秒*/delay(); /*模一尺时间为1秒*/ }return 0;}结果:自动跳出时间7-3 、#include <stdio.h>/*max() 函数功能:找两个数的最大值入口参数:两个整数a,b返回值:两数的最大值*/int max(int a, int b){int max=0;max = (a>b)?a:b;return max;}void main(){int x=0; /*输入的两个数x,y*/int y=0;int m=0; /*m用于接收max()函数的返回值*/printf("input two integer numbers:");scanf("%d,%d",&x,&y);m=max(x,y);printf("the max number is %d\n",m);}结果:7-4#include <stdio.h>/*LCM() 函数功能:计算两个整数的最小公倍数入口参数:两整数a, b返回值:最小公倍数*/int LCM(int a,int b){int i=0; /*循环变量*/int min=0; /*循环寻找范围的最小值*/int max=0; /*循环寻找范围的最大值*/min = (a>b)?a:b; /*最小值为a,b中的最大值*/ max = a*b;/*最大值为a*b*/for (i=min; i<=max; i++){if(i%a==0 && i%b==0)return i;}}void main(){int x; /*键盘输入两整数x,y*/int y;int m; /*m用于接收LCM()函数的返回值*/do{/*输入整数的合法数据*/ printf(" 输入两个正整数: ");scanf("%d,%d",&x,&y);}while(x<0 || y<0);m = LCM(x,y);printf(" 最小公倍数为: %d\n",m);}结果:7-5、#include <stdio.h>long fact(int n);void main(){int i=0; /* 循环变量*/int n=0; /* 输入的值*/int m=0; /* 接收 fact()函数的返回值*/do{printf("input n:");scanf("%d",&n);}while(n<0);for(i=1; i<=n; i++){m=fact(i);printf("%d!=%ld\n",i,m);}}/*fact 函数功能:计算 n!入口参数:n返回值:n!*/long fact(int n){static long p=1;p=p*n;return p;}结果:7-6、#include <stdio.h>long fact(int n);void main(){int i=0; /* 循环变量*/int n=0; /* 输入的值*/int m=0; /* 接收 fact()函数的返回值*/long s=0; /*所求最终结果*/do{printf("input n:");scanf("%d",&n);}while(n<0);for(i=1; i<=n; i++){m=fact(i);s=s+m;}printf("1!+2!+...+n! = %ld\n",s);}/*fact 函数功能:计算 n!入口参数:n返回值:n!*/long fact(int n){static long p=1;p=p*n;return p;}结果:7-7、(1)穷举法:#include <stdio.h>int Gcd(int a,int b);void main(){int x=0; /* 键盘键入两个数 */int y=0;int m=0; /* 接收 Gcd 的返回值*/do{printf(" 输入两个正数 :");scanf("%d,%d",&x,&y);}while(x<0 || y<0);m = Gcd(x,y);printf(" 最大公约数:%d\n",m); }/*Gcd() 函数功能:计算两数的最大公约数入口参数:两个正数 a, b返回值:最大公约数*/int Gcd(int a,int b){int i=0;int t=0;t=(a<b)?a:b; /*t 为 a,b 中的较小者 */ for(i=t; i>=1; i--){if(a%i==0 && b%i==0)return i;}}结果:( 2)欧几里得算法#include <stdio.h>int Gcd(int a,int b);void main(){int x=0; /* 键盘键入两个数 */int y=0;int m=0; /* 接收 Gcd 的返回值*/do{printf(" 输入两个正数 :");scanf("%d,%d",&x,&y);}while(x<0 || y<0);m = Gcd(x,y);printf(" 最大公约数:%d\n",m); }/*Gcd() 函数功能:计算两数的最大公约数入口参数:两个正数 a, b返回值:最大公约数*/int Gcd(int a,int b){int r=0;r=a%b;if(r!=0){do{a=b;b=r;r=a%b;}while(r!=0);}return b;}结果:(3)递归方法:#include <stdio.h>int Gcd(int a,int b);void main(){int x=0; /*键盘键入两个数*/int y=0;int m=0; /* 接收 Gcd 的返回值 */do{printf(" 输入两个正数:");scanf("%d,%d",&x,&y);}while(x<0 || y<0);m = Gcd(x,y);printf(" 最大公约数: %d\n",m); }/*Gcd() 函数功能:计算两数的最大公约数入口参数:两个正数a, b返回值:最大公约数*/int Gcd(int a,int b){if (a==b)/* 递归出口 */return a;else{if(a>b)return Gcd(a-b,b);elsereturn Gcd(b,b-a);}}结果:7-9、#include <stdio.h>/*old() 函数功能:计算第i 个人的年龄入口参数:人数i返回值:年龄*/int old(int i){if(i==1)return 10;elsereturn old(i-1)+2;}void main(){int x=5;/* 人数为 5*/int y=0; /* 接收 old()函数的返回值*/y=old(x);printf(" 第五个人的年龄为:%d\n",y);}结果:7-10、#include <stdio.h>void main(){int flag=0; /* 设置标志变量*/int a=0;/* 百位 */int b=0;/* 十位 */int c=0;/* 个位*/int m=0;/* 代表 acb*/int n=0;/* 代表 bac*/int p=0;/* 代表 bca*/int q=0;/* 代表 cab*/int r=0;/* 代表 cba*/int i=0;/* 从 100~999 中找 abc*/ int sum=0; /* 观众计算得结果*/printf(" 说出你的计算结果: "); scanf("%d",&sum);for(i=100;i<=999;i++){a=i/100;b=i/10%10;c=i%10;m=a*100+c*10+b;n=b*100+a*10+c;p=b*100+c*10+a;q=c*100+a*10+b;r=c*100+b*10+a;if ((m+n+p+q+r)==sum){flag=1;/* 一旦找到就退出循环*/break;}}if(flag==0)/* 未找到说明计算错误 */{printf(" 你算错了!");}else{printf(" 你想的数是 %d %d %d \n",a,b,c);}}结果:二、收集资料并整理,叙述结构化程序设计的基本思想;根据自己的编程,说说你对结构化程序设计的理解。
C语言中关于动态内存分配的详解
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函数是⼀样的,就不在多说了。
C语言动态内存分配的详解及实例
C语⾔动态内存分配的详解及实例1. 动态内存分配的意义(1)C 语⾔中的⼀切操作都是基于内存的。
(2)变量和数组都是内存的别名。
①内存分配由编译器在编译期间决定②定义数组的时候必须指定数组长度③数组长度是在编译期就必须确定的(3)但是程序运⾏的过程中,可能需要使⽤⼀些额外的内存空间2. malloc 和 free 函数(1)malloc 和 free ⽤于执⾏动态内存分配的释放(2)malloc 所分配的是⼀块连续的内存(3)malloc 以字节为单位,并且返回值不带任何的类型信息:void* malloc(size_t size);(4)free ⽤于将动态内存归还系统:void free(void* pointer);(5)_msize(void* pointer)可以获取 malloc 出来的内存空间⼤⼩3. 使⽤ malloc 和 free 需要注意的地⽅(1)malloc 和 free 是库函数,⽽不是系统调⽤(2)malloc 实际分配的内存可能有会⽐请求的多,但不能依赖于不同平台下的 malloc ⾏为。
(3)当请求的动态内存⽆法满⾜时,malloc 返回 NULL(4)当 free 的参数为 NULL 时,函数直接返回malloc(0)返回什么?#include <stdio.h>#include <malloc.h>int main(){int i=10;int* p= NULL;for(i=0;i<100;i++){//注意,malloc(0)会返回⼀个有效的内存地址,⼤⼩为1//但我们不能依赖编译器的这种⾏为来使⽤这个字节的空间!p = (int*)malloc(i);printf("%d ",_msize(p));//返回malloc出来的内存空间⼤⼩free(p);}return 0;}内存泄漏检测模块mleak.h#ifndef _MLEAK_H_#define _MLEAK_H_#include <stdio.h>#include <malloc.h>#define MALLOC(n) mallocEx(n, __FILE__, __LINE__)#define FREE(p) freeEx(p)void* mallocEx(size_t n, const char* file, const line);void freeEx(void* p);void PRINT_LEAK_INFO();#endifmleak.c复制代码#include "mleak.h"#define SIZE 256//动态内存申请参数结构体typedef struct{void* pointer;//申请到的内存地址int size; //内存块⼤⼩const char* file; //⽂件名int line; //⽂件⾏号}MItem;static MItem g_record[SIZE]; //记录每个动态内存申请的操作void* mallocEx(size_t n, const char* file, const line){int i = 0;void* ret = malloc(n);//动态内存申请if(ret != NULL){//申请成功,则记录下来//遍历全局数组,记录此次操作for(i = 0; i< SIZE; i++){//查找位置if(g_record[i].pointer == NULL){g_record[i].pointer = ret;g_record[i].size = n;g_record[i].file = file;g_record[i].line = line;break;}}}return ret;}void freeEx(void* p){if(p != NULL){int i = 0;//遍历全局数组,释放内存空间,并清除操作记录for(i = 0; i< SIZE; i++){if(g_record[i].pointer == p){g_record[i].pointer = NULL;g_record[i].size = 0;g_record[i].file = NULL;g_record[i].line = 0;free(p);break;}}}}void PRINT_LEAK_INFO(){int i = 0;printf("Potenital Memory Leak Info:\n");//遍历全局数组,打印未释放的空间的申请记录for(i = 0; i< SIZE; i++){//查找位置if(g_record[i].pointer != NULL){printf("Address:%p, size:%d, Location:%s:%d\n",g_record[i].pointer,g_record[i].size,g_record[i].file,g_record[i].line);}}}testc.#include <stdio.h>#include "mleak.h"void f(){//没释放,会造成内存泄漏!MALLOC(100);}int main(){int* p = (int*)MALLOC(3 * sizeof(int));f();p[0] = 1;p[1] = 2;p[2] = 3;FREE(p);PRINT_LEAK_INFO();return 0;}/*输出结果:E:\Study>gcc test.c mleak.cE:\Study>a.exePotenital Memory Leak Info:Address:00602ED8, size:100, Location:38-1.c:7*/4. calloc 和 realloc 函数(1)malloc 的同胞兄弟:void* calloc(size_t num, size_t size);void* realloc(void* pointer,size_t new_size);(2)calloc 参数表⽰要返回 num 个某种类型(如 sizeof(int))⼤⼩的内存空间。
操作系统内存管理之(动态及静态)内存分配_基础知识习题及答案
操作系统之(动态/静态)内存分配_基础知识习题(答案见尾页)一、选择题1. 静态内存分配的原理与过程是什么?A. 将分配给程序的内存空间在编译时确定B. 在运行时根据程序需求动态分配内存C. 通过操作系统的内存管理器进行内存分配D. 以上都是2. 静态内存分配的优点和缺点分别是什么?A. 优点:内存分配可靠,缺点:内存占用较大,灵活性较差B. 优点:内存占用较小,缺点:分配不灵活C. 优点:分配灵活,缺点:内存占用较大D. 优点:内存占用较少,缺点:分配不可靠3. 以下哪种方法不是静态内存分配的方式?A. 预分配内存B. 申请-分配内存C. 复制分配D. 自由式内存分配4. 以下哪个选项描述了静态内存分配的过程?A. 先申请,后分配B. 先分配,后申请C. 分配-申请D. 申请-分配-释放5. 静态内存分配中,如何解决内存泄漏的问题?A. 释放不再使用的内存B. 使用垃圾回收机制C. 重新申请新的内存D. 以上都是6. 以下哪个算法可以用于静态内存分配?A. 线性搜索B. 排序C. 插入排序D. 选择排序7. 以下哪个选项不是静态内存分配的一种方式?A. 直接分配B. 动态分配C. 分块分配D. 复制分配8. 在静态内存分配中,哪种情况下可能会发生内存碎片?A. 分配的内存大小合适B. 分配的内存大小较小C. 多次分配和释放内存D. 没有内存碎片问题9. 以下哪种算法适用于静态内存分配?A. 快速排序B. 归并排序C. 堆排序D. 以上都不适用10. 静态内存分配中,如何优化内存使用效率?A. 合理分配内存大小B. 避免内存浪费C. 增加内存缓存D. 以上都是11. 动态内存分配的原理与过程是什么?A. 分配一段连续的内存空间给程序B. 在程序运行过程中,根据需要分块分配内存C. 使用操作系统的内存管理器进行动态分配D. 以上都是12. 动态内存分配的优点和缺点分别是什么?A. 优点:内存分配灵活,缺点:分配效率较低B. 优点:分配效率较高,缺点:内存占用较大C. 优点:分配灵活,缺点:分配不灵活D. 优点:内存占用较少,缺点:分配不可靠13. 以下哪种方法不是动态内存分配的方式?A. 预分配内存B. 申请-分配内存C. 复制分配D. 自由式内存分配14. 以下哪个选项描述了动态内存分配的过程?A. 先申请,后分配B. 先分配,后申请C. 分配-申请D. 申请-分配-释放15. 动态内存分配中,如何解决内存泄漏的问题?A. 释放不再使用的内存B. 使用垃圾回收机制C. 重新申请新的内存D. 以上都是16. 以下哪个算法可以用于动态内存分配?A. 线性搜索B. 排序C. 插入排序D. 选择排序17. 以下哪个选项不是动态内存分配的一种方式?A. 直接分配B. 动态分配C. 分块分配D. 复制分配18. 在动态内存分配中,哪种情况下可能会发生内存泄漏?A. 分配的内存大小合适B. 分配的内存大小较小C. 多次分配和释放内存D. 没有内存泄漏问题19. 以下哪种算法适用于动态内存分配?A. 快速排序B. 归并排序C. 堆排序D. 以上都不适用20. 动态内存分配中,如何优化内存使用效率?A. 合理分配内存大小B. 避免内存浪费C. 增加内存缓存D. 以上都是21. 静态内存分配和动态内存分配的内存使用情况有何不同?A. 静态内存分配内存占用较大,动态内存分配内存占用较小B. 动态内存分配内存占用较大,静态内存分配内存占用较小C. 两种内存分配方式内存占用情况相似D. 无法比较22. 静态内存分配和动态内存分配的性能差异如何?A. 静态内存分配性能较高,动态内存分配性能较低B. 动态内存分配性能较高,静态内存分配性能较低C. 两种内存分配方式性能相似D. 无法比较23. 在什么情况下,应该选择静态内存分配而不是动态内存分配?A. 程序需要分配固定大小的内存空间B. 程序需要频繁地分配和释放内存C. 内存占用较小D. 以上都是24. 在什么情况下,应该选择动态内存分配而不是静态内存分配?A. 程序需要分配动态增长的内存空间B. 程序不需要分配固定大小的内存空间C. 内存占用较大D. 以上都是25. 以下哪种说法是错误的?A. 静态内存分配是在编译期间完成的B. 动态内存分配是在运行期间完成的C. 静态内存分配通常比动态内存分配更高效D. 动态内存分配需要使用额外的内存管理开销26. 以下哪种方法不是静态内存分配的特点?A. 分配内存的过程与程序无关B. 分配内存的大小在编译期间确定C. 分配内存的过程与程序相关D. 内存分配需要在运行期间进行27. 以下哪种方法不是动态内存分配的特点?A. 分配内存的过程与程序无关B. 分配内存的大小在编译期间确定C. 分配内存的过程与程序相关D. 内存分配需要在运行期间进行28. 在进行静态内存分配时,哪种内存管理策略是正确的?A. 一次分配,多次释放B. 按需分配,分配-释放C. 先分配,后释放D. 以上都不是29. 在进行动态内存分配时,哪种内存管理策略是正确的?A. 按需分配,分配-释放B. 一次分配,多次释放C. 先分配,后释放D. 以上都不是30. 如何根据程序的需求选择合适的内存分配方式?A. 根据程序的内存需求和使用场景选择静态内存分配或动态内存分配B. 根据程序的性能要求选择静态内存分配或动态内存分配C. 根据程序的内存需求和使用场景选择是否使用内存分配D. 以上都是31. 内存分配算法的主要目的是什么?A. 提高内存利用率B. 减少内存分配的时间C. 减少内存泄漏的问题D. 以上都是32. 以下哪种算法不能用于内存分配?A. 线性搜索B. 排序C. 插入排序D. 选择排序33. 以下哪种算法适用于小规模内存分配?B. 排序C. 插入排序D. 选择排序34. 以下哪种算法适用于大规模内存分配?A. 线性搜索B. 排序C. 插入排序D. 选择排序35. 以下哪种算法可以保证内存分配的公平性?A. 线性搜索B. 排序C. 插入排序D. 选择排序36. 以下哪种算法可以保证内存分配的效率?A. 线性搜索B. 排序C. 插入排序D. 选择排序37. 以下哪种算法在内存分配时需要额外的内存开销?A. 线性搜索B. 排序C. 插入排序D. 选择排序38. 以下哪种算法适用于具有随机访问特性的数据结构?A. 线性搜索B. 排序C. 插入排序39. 以下哪种算法适用于具有顺序访问特性的数据结构?A. 线性搜索B. 排序C. 插入排序D. 选择排序40. 以下哪种算法适用于具有插入访问特性的数据结构?A. 线性搜索B. 排序C. 插入排序D. 选择排序二、问答题1. 静态内存分配的原理与过程2. 静态内存分配的优缺点3. 动态内存分配的原理与过程4. 动态内存分配的优缺点5. 内存使用情况与性能差异6. 适用场景选择参考答案选择题:1. D2. A3. D4. A5. D6. A7. B8. C9. D 10. D11. D 12. A 13. D 14. A 15. D 16. B 17. A 18. C 19. C 20. D21. B 22. B 23. D 24. A 25. C 26. C 27. B 28. C 29. A 30. A31. D 32. B 33. A 34. D 35. D 36. D 37. D 38. A 39. C 40. C问答题:1. 静态内存分配的原理与过程静态内存分配是在程序编译期间完成内存空间的分配,其原理是根据程序的需求和系统的限制,提前确定好内存的使用情况。
C Primer Plus 第七章编程练习参考答案
#include <stdio.h>int main(void){char ch;int sp_ct, nl_ct, other;sp_ct = nl_ct = other = 0;while ((ch = getchar()) != '#'){if (ch == ' ')sp_ct++;else if (ch == '\n')nl_ct++;elseother++;}printf("%d whitespace, %d newline, %d other.\n", sp_ct, nl_ct, other);return 0;}#include <stdio.h>int main(void){char ch;int count = 0;while ((ch = getchar()) != '#') {if (ch == '\n')continue;count ++;putchar(ch);printf("/%d ", ch);if (count % 8 == 0)printf("\n");}printf("That's all!");return 0;}#include <stdio.h>int main(void){int num;int e_ct, o_ct;double e_sum, o_sum;e_ct = o_ct = 0;e_sum = o_sum = 0.0;printf("Enter the integer:(0 to quit).\n");while (scanf("%d", &num) == 1 && num != 0) {if (num % 2 == 0){e_ct++;e_sum += num;}else{o_ct++;o_sum += num;}printf("Enter next integer:(0 to quit).\n");}printf("%d even entered.", e_ct);if (e_ct > 0)printf(" Average is %g.", e_sum / e_ct);putchar('\n');printf("%d odd entered.", o_ct);if (o_ct > 0)printf(" Average is %g.", o_sum / o_ct);putchar('\n');printf("Done!\n");return 0;}/* programming exercise 7-4 */#include <stdio.h>#define ECM '!'int main(void){char ch;int fs_ct = 0;int em_ct = 0;while ((ch = getchar()) != '#'){if (ch == '.'){putchar(ECM);fs_ct++;}else if (ch == '!'){putchar(ECM);putchar(ECM);em_ct++;}elseputchar(ch);}printf("%d times fs to em, %d times em to double em.\n", fs_ct, em_ct);return 0;}/* programming exercise 7-5 */#include <stdio.h>int main(void){int num;int e_ct = 0, o_ct = 0;double e_sum = 0.0, o_sum = 0.0;printf("Enter the integer:(0 to quit).\n");while (scanf("%d", &num) == 1 && num != 0) {switch(num % 2){case 0:e_ct++;e_sum += num;break;case 1:o_ct++;o_sum += num;break;}printf("Enter next integer:(0 to quit).\n");}printf("%d even entered.", e_ct);if (e_ct > 0)printf(" Average is %g.", e_sum / e_ct);putchar('\n');printf("%d odd entered.", o_ct);if (o_ct > 0)printf(" Average is %g.", o_sum / o_ct);putchar('\n');printf("Done!\n");return 0;}/* programming exercise 7-6 */#include <stdio.h>int main(void){char ch;char prev = 0;/* 记得对prev进行0填充,否则有可能定义的内存的垃圾数据恰好为e */int count = 0;while ((ch = getchar()) != '#'){if (ch == 'i' && prev == 'e')count++;prev = ch;}switch (count){case 0:printf("\"ei\" no apeared.\n");break;case 1:printf("\"ei\" apeared 1 time.\n");break;default:printf("\"ei\" apeared %d times", count);}return 0;}/* programming exercise 7-7 */#include <stdio.h>#define BASEPAY 10#define BASEHRS 40#define OVERRATE 1.5#define LEVEL1 300#define LEVEL2 150#define TAX1 0.15#define TAX2 0.20#define TAX3 0.25int main(void){float hours;float total, tax, net;printf("Please enter your work time: ");scanf("%f", &hours);if (hours > BASEHRS)total = BASEPAY * (BASEHRS + (hours - BASEHRS) * OVERRATE);elsetotal = hours * BASEPAY;if (total <= LEVEL1)tax = total * TAX1;else if (total <= (LEVEL1 + LEVEL2))tax = LEVEL1 * TAX1 + (total - LEVEL1) * TAX2;elsetax = LEVEL1 * TAX1 + LEVEL2 * TAX2 + (total - LEVEL1 - LEVEL2) * TAX3;net = total - tax;printf("total = %g, tax = %g, net = %g.\n",total, tax, net);return 0;}/* programming exercise 7-8 */#include <stdio.h>#define BASEHRS 40#define OVERRATE 1.5#define T_LEVEL1 300#define T_LEVEL2 150#define S_LEVEL1 8.75#define S_LEVEL2 9.33#define S_LEVEL3 10.00#define S_LEVEL4 11.20#define TAX1 0.15#define TAX2 0.20#define TAX3 0.25int main(void){float hours;float basepay;float total, tax, net;int choice;printf("****************************************************** ***********\n");printf("Enter the number corresponding to the desired payrate or action:\n");printf("1)$8.75/hr 2)$9.33/hr\n");printf("3)$10.00/hr 4)$11.20/hr\n");printf("5)quit\n");printf("****************************************************** ***********\n");while (scanf("%d", &choice) == 1 && choice != 5){switch(choice){case 1:basepay = S_LEVEL1;break;case 2:basepay = S_LEVEL2;break;case 3:basepay = S_LEVEL3;break;case 4:basepay = S_LEVEL4;break;default:printf("You should enter the number between 1 to 4 (5 to quit).\n");printf("Please enter the right number: \n");continue;}printf("Please enter your work time: ");scanf("%f", &hours);if (hours > BASEHRS)total = basepay * (BASEHRS + (hours - BASEHRS) * OVERRATE);elsetotal = hours * basepay;if (total <= T_LEVEL1)tax = total * TAX1;else if (total <= (T_LEVEL1 + T_LEVEL2))tax = T_LEVEL1 * TAX1 + (total - T_LEVEL1) * TAX2;elsetax = T_LEVEL1 * TAX1 + T_LEVEL2 * TAX2 + (total - T_LEVEL1 - T_LEVEL2) * TAX3;net = total - tax;printf("total = %g, tax = %g, net = %g.\n",total, tax, net);printf("Please enter next number:\n");}printf("That's all!\n");return 0;}/* programmming exercise 7-9 */#include <stdio.h>int main(void){int num;int div;int count;printf("Please enter the limit in integer:\n");scanf("%d", &num);while (num >1){for (div = 2, count = 0; div <= num / 2; div++){if(num % div == 0)count++;}if (count == 0)printf("%d ", num);num--;}printf("\nThat's all!\n");return 0;}/* programming exercise 7-10 */#include <stdio.h>#define RATE1 0.15#define RATE2 0.28#define LEVEL1 17850#define LEVEL2 23900#define LEVEL3 29750#define LEVEL4 14875int main(void){double tax;double income;int type;long level;printf("Please choose your type as follow:(q to quit)\n");printf("1)Single; 2)Householder;\n");printf("3)Married; 4)Divorced\n");while (scanf("%d", &type) == 1){switch (type){case 1:level = LEVEL1;break;case 2:level = LEVEL2;break;case 3:level = LEVEL3;break;case 4:level = LEVEL4;break;default:printf("You should choose the number""between 2 and 4(q to quit).\n");printf("Please enter the right number:\n");continue;}printf("Please enter your income:\n");scanf("%lf", &income);if (income <= level)tax = income * RATE1;elsetax = level * RATE1 + (income - level) * RATE2;printf("Your taxes is %g.\n", tax);printf("Please enter next type in integer:(q to quit)\n");}printf("That's all!\n");return 0;}/* programming exercise 7-11 */ #include <stdio.h>#include <stdbool.h>#define WT_LEVEL1 5#define WT_LEVEL2 20#define FR_LEVEL1 3.5#define FR_LEVEL2 10#define FR_LEVEL3 8#define FR_OVER 0.1#define DISCOUNT 0.05#define AC_PRC 1.25#define BT_PRC 0.65#define CR_PRC 0.89int main(void){char a, b, c;char ch;float a_wt = 0, b_wt = 0, c_wt = 0;float total_wt;float cost, total_cost, freight;int discount = 0;printf("************************************************\n");printf("Please choose the vegatable and weight you want:\n");printf("(type as follow, q to quit)\n");printf("a) artichoke; b) beet; c) carrot;\n");printf("************************************************\n");while ((ch = getchar()) != 'q'){switch (ch){case 'a':printf("You select artichoke, enter the weight:\n");scanf("%f", &a_wt);break;case 'b':printf("You select beet, enter the weight:\n");scanf("%f", &b_wt);break;case 'c':printf("You select carrot, enter the weight:\n");scanf("%f", &c_wt);break;default:printf("Please enter a, b, or c:\n");continue;}printf("Other vegatable?\n");}printf("\n%g %s artichoke, %g %s beet, %g %s carrot.\n", a_wt, a_wt > 1 ? "pounds" : "pound",b_wt, b_wt > 1 ? "pounds" : "pound",c_wt, c_wt > 1 ? "pounds" : "pound");total_wt = a_wt + b_wt + c_wt;cost = a_wt * AC_PRC + b_wt * BT_PRC + c_wt * CR_PRC;if (cost >= 100){cost *= (1 - DISCOUNT);discount++;}if (total_wt == 0)freight = 0;else if (total_wt <= 5)freight = FR_LEVEL1;else if (total_wt < 20)freight = FR_LEVEL2;elsefreight = FR_LEVEL3 + total_wt * FR_OVER;total_cost = cost + freight;printf("Average cost is $%g per pound, tatol weight is %g %s,\n" ,total_cost / total_wt, total_wt, total_wt > 1 ? "pounds" : "pound");printf("total cost is $%g, and %d%% off, freight is $%g.\n", total_cost, discount == 1 ? 5 : 0, freight);return 0;}。
实验7+动态内存分配
实验七一、编程题1.编写函数int prime_m( int n,int x[], long y[]),在2~n范围内查找同时符合以下条件的整数m:2m -1是素数、2m -1的反序数是奇数、2m -1的十进制表示中包含数字1。
将2~n范围内符合上述条件的所有整数m依次保存到x指向的数组中,将与m对应的整数2m -1依次保存到y指向的数组中。
函数返回x数组中保存的整数个数。
2.编写main函数,接收键盘输入的n值,调用prime_m函数找到2~n范围内所有符合给定条件的整数m及整数2m -1并将它们分别保存在两个一维数组中.3.【测试数据与运行结果】测试数据: n=20输出结果:5 317 12717 131071二、编程题接收从键盘输入的若干个字符串,为每一个字符串动态申请一块存储区,将字符串复制到该存储区并将存储区的首地址依次保存到指针数组lineptr中,再以字典序输出所有的字符串(输入时以回车<CR>作为字符串之间的分隔符,以空串作为输入结束标记,输入的字符串总数不超过10个)。
函数void sort(char *vp[ ], int n)的功能是根据指针数组vp前n 个元素指向的字符串,按字典序对指针数组排序。
函数void outline(char *vp[ ], int n) 的功能是输出指针数组vp前n个元素指向的字符串。
【测试数据与运行结果】输入:输出(排序后):No<CR> NoWell<CR> PracticeYou <CR> WellPractice<CR> You<CR>(空串)附加题:一、改错题【程序功能】为了测试学生对英文单词的掌握程度,以下程序在给出的五个单词中随机抽取一个单词,用“*”替换该单词中的两个随机位置上的字母并显示替换后的单词,再将被测学生输入的单词与正确单词比较,显示对错信息。
提示:库函数srand( )初始化随机数生成器,库函数rand( )%n随机产生0~(n-1)之间的一个整数并返回,这两个函数的原型包含在stdlib.h中。
【c++习题】【17416】动态分配内存
【c++习题】【17416】动态分配内存#include<iostream>#include<cstring>#define N 100using namespace std;class String{public:String(const string&);void display() { cout<<Head<<endl; }void re();~String() { delete[] Head; }private:char *Head;};String::String(const string &str){Head = new char[100];for(int i = 0; i != str.size(); ++i){Head[i] = str[i];}}void String::re(){for(int i = 0, j = strlen(Head) - 1; i < j; ++i, --j) {swap(Head[i], Head[j]);}}int main(){string str = "hi~";String s(str);s.display();s.re();s.display();return0;}⼀、动态分配内存。
1、像上⾯那样:a-动态分配,通常在构造器⾥完成。
char *Head;Head = new char[100];b-删除。
~String() { delete[] Head; }越界访问的结果是未知的。
#include <iostream>#include <cstdio>#include <string>using namespace std;int main(){int n;cin >> n;int *a;a = new int[n];printf("size of a=%d\n", n);for (int i = 0; i != n; ++i) {a[i] = i;// 动态分配内存后表现得和数组⼀模⼀样~cout << a[i] << endl;}// 表忘记删除delete [] a;printf("delete a!");return0;2、还有个技巧就是⽤来重新初始化,#include <iostream>#include <cstdio>#include <string>using namespace std;int main(){char *word;word = new char[100];char c;int i = 0;cout << "Create word array and enter the words." << endl;while (cin >> c) {word[i++] = c;}cout << "word:" << word << '\n';delete [] word;cout << "Delete word:" << endl;cout << "word:" << word << '\n';return0;}char *word在c++中表现得和常量字符串是⼀样的。
C++电子课件(中)第七章
2021/7/13
15
7.1.3 浅复制与深复制
浅复制: 默认复制构造函数,可用一个类对象
初始化另一个类对象,称为默认的按成员复制,而不是 对整个类对象的按位复制。这称为浅复制。
P
obj1
自由存 储区对 象
P
o制
P
obj2
复制后
如果类中有一个数据成员为指针,该类的一个对象obj1中 的这个指针p,指向了动态分配的一个自由存储区对象,(参见 图7.1复制前),如果用obj1按成员复制了一个对象obj2,这时 obj2.p也指向同一个自由存储区对象。
类对象动态建立与删除过程:
通过new建立的对象要调用构造函数,通过delete删除对 象也要调用析构函数。
CGoods *pc; pc=new CGoods; //分配自由存储区空间,并构造一个无名的CGoods对象; ……. delete pc; //先析构,然后将内存空间返回给自由存储区;
自由存储区对象的生命期并不依赖于建立它的作用域,所以 除非程序结束,自由存储区对象(无名对象)的生命期不会 到期,并且需要显式地用delete语句析构该类对象,上例执 行delete语句时,C++自动调用商品类的析构函数。
申请和释放自由存储区中分配的存贮空间,分别使用new
和delete的两个运算符来完成,其使用的格式如下:
指针变量名=new 类型名(初始化式); delete 指针名;
new运算符返回的是一个指向所分配类型变量(对象)的
指针。对所创建的变量或对象,都是通过该指针来间接操作的,
而动态创建的对象本身没有名字。
5.动态分配的变量或对象的生命期。无名对象的生命期 并不依赖于建立它的作用域,比如在函数中建立的动态对 象在函数返回后仍可使用。但必须记住释放该对象所占自 由存储区空间,并只能释放一次,在函数内建立,而在函 数外释放是一件很容易失控的事,往往会出错。
C 第七章习题解答new范文
第七章动态内存分配习题一、基本概念与基础知识自测题7.1 填空题7.1.1 C/C++定义了4个内存区间:(1)、(2)、(3)和(4)。
答案:(1)代码区,存放程序代码;(2)全局变量与静态变量区,存放全局变量或对象(包括静态);(3)局部变量区即栈(stack)区,存放局部变量;(4)动态存储区,即堆(heap)区或自由存储区(free store)。
7.1.2 静态定义的变量和对象用标识符命名,称为(1);而动态建立的称为(2),动态建立对象的初始化是通过(3)来(4)。
答案:(1)命名对象(2)无名对象(3)初始化式(initializer)(4)显式初始化7.1.3 在用new运算符建立一个三维数组15*30*10时,使用了(1)个下标运算符,对应的用delete运算符注销这个三维数组时使用了(2)个下标运算符。
new返回的指针是指向(3)的指针。
答案:(1)3个(2)1个(3)30行10列的2位数组7.1.4 当动态分配失败,系统采用(1)来表示发生了异常。
如果new返回的指针丢失,则所分配的堆空间无法收回,称为(2)。
这部分空间必须在(3)才能找回,这是因为无名对象的生命期(4)。
答案:(1)返回一个空指针(NULL)(2)内存泄漏(3)重新启动计算机后(4)并不依赖于建立它的作用域7.1.5 按语义的缺省的构造函数和拷贝构造赋值操作符实现的拷贝称(1),假设类对象obj中有一个数据成员为指针,并为这个指针动态分配一个堆对象,如用obj1按成员语义拷贝了一个对象obj2,则obj2对应指针指向(2)。
答案:(1)浅拷贝(2)同一个堆对象7.1.6 单链表的结点包含两个域:(1)和(2)。
使用链表的最大的优点是(3),即使是动态数组也做不到这一点。
答案:(1)数据域(2)指针域(3)用多少空间,开多少空间27.1.7 进入单链表必须通过单链表的(1),如果它丢失则(2),内存也(3),在单链表中进行的查找只能是(4)。
C++第七章习题解答new
第七章动态内存分配习题一、基本概念与基础知识自测题7.1 填空题7.1.1 C/C++定义了4个内存区间:(1)、(2)、(3)和(4)。
答案:(1)代码区,存放程序代码;(2)全局变量与静态变量区,存放全局变量或对象(包括静态);(3)局部变量区即栈(stack)区,存放局部变量;(4)动态存储区,即堆(heap)区或自由存储区(free store)。
7.1.2 静态定义的变量和对象用标识符命名,称为(1);而动态建立的称为(2),动态建立对象的初始化是通过(3)来(4)。
答案:(1)命名对象(2)无名对象(3)初始化式(initializer)(4)显式初始化7.1.3 在用new运算符建立一个三维数组15*30*10时,使用了(1)个下标运算符,对应的用delete运算符注销这个三维数组时使用了(2)个下标运算符。
new返回的指针是指向(3)的指针。
答案:(1)3个(2)1个(3)30行10列的2位数组7.1.4 当动态分配失败,系统采用(1)来表示发生了异常。
如果new返回的指针丢失,则所分配的堆空间无法收回,称为(2)。
这部分空间必须在(3)才能找回,这是因为无名对象的生命期(4)。
答案:(1)返回一个空指针(NULL)(2)内存泄漏(3)重新启动计算机后(4)并不依赖于建立它的作用域7.1.5 按语义的缺省的构造函数和拷贝构造赋值操作符实现的拷贝称(1),假设类对象obj中有一个数据成员为指针,并为这个指针动态分配一个堆对象,如用obj1按成员语义拷贝了一个对象obj2,则obj2对应指针指向(2)。
答案:(1)浅拷贝(2)同一个堆对象7.1.6 单链表的结点包含两个域:(1)和(2)。
使用链表的最大的优点是(3),即使是动态数组也做不到这一点。
答案:(1)数据域(2)指针域(3)用多少空间,开多少空间7.1.7 进入单链表必须通过单链表的(1),如果它丢失则(2),内存也(3),在单链表中进行的查找只能是(4)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第七章动态内存分配习题
一、基本概念与基础知识自测题
7.1 填空题
7.1.1 C/C++定义了4个内存区间:(1)、(2)、(3)和(4)。
答案:(1)代码区,存放程序代码;
(2)全局变量与静态变量区,存放全局变量或对象(包括静态);
(3)局部变量区即栈(stack)区,存放局部变量;
(4)动态存储区,即堆(heap)区或自由存储区(free store)。
7.1.2 静态定义的变量和对象用标识符命名,称为(1);而动态建立的称为(2),动
态建立对象的初始化是通过(3)来(4)。
答案:(1)命名对象
(2)无名对象
(3)初始化式(initializer)
(4)显式初始化
7.1.4 当动态分配失败,系统采用(1)来表示发生了异常。
如果new返回的指针丢失,
则所分配的堆空间无法收回,称为(2)。
这部分空间必须在(3)才能找回,这是因为无名对象的生命期(4)。
答案:(1)返回一个空指针(NULL)
(2)内存泄漏
(3)重新启动计算机后
(4)并不依赖于建立它的作用域
7.1.5 按语义的缺省的构造函数和拷贝构造赋值操作符实现的拷贝称(1),假设类对象
obj中有一个数据成员为指针,并为这个指针动态分配一个堆对象,如用obj1按成员语义拷贝了一个对象obj2,则obj2对应指针指向(2)。
答案:(1)浅拷贝
(2)同一个堆对象
7.2简答题(以下习题题号可能和教材不一致!)
7.2.1用delete删除p所指向的无名对象时,p指针也同时被删除了,对不对?为什么?答:不对。
注意这时释放了p所指向的无名对象占用的内存空间,也就是撤销了该无名对象,称动态内存释放(dynamic memory deallocation),但指针p本身并没有撤销,它仍然存在,该指针所占内存空间并未释放。
7.2.2为什么动态建立类对象数组时,类的定义一定要有缺省的构造函数?
答:new后面类(class)类型也可以有参数。
这些参数即构造函数的参数。
但对创建数组,没有参数,只能调用缺省的构造函数。
7.2.3要实现深拷贝,自定义的拷贝构造函数应该怎样设计?
答:如果类中有一个数据成员为指针,该类的一个对象中的这个指针p,指向了动态分配的一个堆对象。
深拷贝时要给新建立的对象独立分配一个堆对象。
这时拷贝的构造函数应
该设计为:先拷贝对象主体,再为新建对象的指针分配一个堆对象,最后用原对象的堆对象拷贝新对象的堆对象。
即分三步完成。