【C++同步练习】内存管理 - 教程

个人主页:小年糕是糕手

个人专栏:《C++》《C++同步练习》《数据结构》《C语言》

你不能左右天气,但你可能改变心情;你不能改变过去,但你能够决定未来!



目录

一、内存划分

二、C++中的new / delete


一、内存划分

知识回顾:

  1. 本质:程序运行时操作系统分配的内存区域,按功能划分为不同段,管理材料的存储与生命周期。
  2. 核心目的:合理管理不同类型信息的存储(如临时变量、全局数据、动态内存),优化资源使用与访问效率。
  3. 基本划分(常见区域)
    1. 栈区(Stack):存储局部变量、函数参数、返回地址;自动分配 / 释放,空间小、速度快。
    2. 堆区(Heap):存储动态分配数据(如new/malloc申请的内存);手动分配 / 释放,空间大、灵活但需自行管理。
    3. 全局 / 静态区:存储全局变量、静态变量(static修饰);程序启动时分配,结束时释放。
    4. 代码段:存储代码的二进制指令;只读、共享。
    5. 常量区:存储字符串常量等不可修改数据;只读。
  4. 核心特点
    1. 不同区域的生命周期不同(栈区随函数调用销毁,堆区手动控制,全局区随程序生命周期);
    2. 不同区域的访问权限不同(代码段 / 常量区只读,栈 / 堆 / 全局区可读可写)。

1、看下列代码,解除下列障碍:

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
	static int staticVar = 1;
	int localVar = 1;
	int num1[10] = {1, 2, 3, 4};
	char char2[] = "abcd";
	char* pChar3 = "abcd";
	int* ptr1 = (int*)malloc(sizeof (int)*4);
	int* ptr2 = (int*)calloc(4, sizeof(int));
	int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);
	free (ptr1);
	free (ptr3);
}

答案、解析:

2、下面有关c++内存分配堆栈说法错误的是()

A.对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制

B. 对于栈来讲,生长方向是向下的,也就是向着内存地址减小的方向;对于堆来讲,它的生长方向是向上的,是向着内存地址增加的方向增长

C.对于堆来讲,频繁的 new / delete 势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题

D.一般来讲在 32 位体系下,堆内存可以达到4G的空间,但是对于栈来讲,一般都是有一定的空间大小的

答案:D

解析:

A:栈区主要存在局部变量和函数参数,其空间的管理由编译器自动完成,无需手动控制,堆区是自己申请的空间,在不需要时需要手动释放

B:栈区先定义的变量放到栈底,地址高,后定义的变量放到栈顶,地址低,因此是向下生长的,堆区则相反

C:频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此难题

D:32位框架下,最大的访问内存空间为4G,所以不可能把所有的内存空间当做堆内存使用,故错误

3、C++中关于堆和栈的说法,哪个是错误的()

A.堆的大小仅受操作系统的限制,栈的大小一般较小

B.在堆上频繁的调用new/delete容易产生内存碎片,栈没有这个问题

C.堆和栈都可以静态分配

D.堆和栈都可以动态分配

答案:C

解析:

A:堆大小受限于操作系统,而栈空间一般有系统直接分配

B:频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题

C:堆无法静态分配,只能动态分配

D:栈可以通过函数_alloca进行动态分配,不过注意,所分配空间不能通过free或delete进行释放

二、C++中的new / delete

知识回顾:

  1. 本质:C++ 中用于动态内存管理的运算符,对应 C 语言的malloc/free,但会自动调用对象的构造 / 析构函数。
  2. 核心目的:在堆区手动分配 / 释放内存,管理对象的动态生命周期(按需创建 / 销毁,灵活控制内存)。
  3. 基本用法
    1. new类型* 指针 = new 类型(初始化值);(分配单个对象);类型* 指针 = new 类型[数量];(分配对象数组);分配时自动调用构造函数。
    2. deletedelete 指针;(释放单个对象);delete[] 指针;(释放对象数组);释放时自动调用析构函数。
  4. 规则
    1. newdelete必须匹配使用(单个对象对应delete,数组对应delete[],否则可能内存泄漏 / 未调用析构);
    2. new分配失败,会抛出bad_alloc异常(C++11 后可使用new(nothrow)返回空指针);
    3. 堆指针),需确保析构函数中释放资源,避免内存泄漏。就是对于含动态资源的对象(如成员

1、c++语言中,类ClassA的构造函数和析构函数的执行次数分别为()

ClassA *pclassa=new ClassA[5];

delete pclassa;

A.5,1     B.1,1     C.5,5     D.程序可能崩溃

答案:D

解析:

A:申请对象数组,会调用构造函数5次,delete由于没有使用[ ],此时只会调用一次析构函数,但往往会引发程序崩溃

B:构造函数会调用5次

C:析构函数此时只会调用1次,要想完整释放数组空间,需要使用[ ]

D:正确

2、函数参数使用的空间是在()中申请的,malloc或new是在()中申请空间的?

A.堆,栈      B.栈,堆     C.栈, 栈     D.堆,堆

答案:B

解析:

A:参数在栈空间存放,malloc或new申请的空间为堆区

B:正确

C:参数在栈空间存放,malloc或new申请的空间为堆区

D:参数在栈空间存放,malloc或new申请的空间为堆区

3、下面有关malloc和new,说法错误的是()

一块内存就是A.new 是创建一个对象(先分配空间,再调构造函数初始化), malloc分配的

B.new 初始化对象,调用对象的构造函数,对应的delete调用相应的析构函数,malloc仅仅分配内存,free仅仅回收内存

C.new和malloc都是保留字,不需要头文件支持

一个函数就是D.new和malloc都可用于申请动态内存,new是一个操作符,malloc是

答案:C

解析:

A:new会申请空间,同时调用构造函数初始化对象,malloc只做一件事就是申请空间

B:new / delete与malloc / free最大区别就在于是否会调用构造函数与析构函数

C:需要头文件malloc.h,只是平时该头文件已经被其他头文件所包含了,用的时候很少单独引入,故错误

函数就是D:new是操作符,malloc

4、设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为()

C c;

void main()

{

A*pa=new A();

  B b;

static D d;

delete pa;

}

答案:ABDC

解析:

首先手动释放pa, 所以会先调用A的析构函数,其次会跟定义相反的顺序释放局部对象,这里只有b,就释放b,再释放静态局部对象d,再释放全局对象c

5、运用 char* p = new char[100]申请一段内存,然后采用delete p释放,有什么问题()

A.会有内存泄露

B.不会有内存泄露,但不建议用

C.编译就会报错,必须使用delete [ ]p

D.编译没问题,运行会直接崩溃

答案:B

解析:

A:对于内置类型,此时delete就相当于free,因此不会造成内存泄漏

B:正确

C:编译不会报错,建议针对数组释放使用delete[ ](如果是自定义类型,不利用方括号就会运行时错误)

D:对于内置类型,程序不会崩溃,但不建议这样启用

6、以下代码中,A 的构造函数和析构函数分别执行了几次:()

A*pa=new A[10];

delete [ ]pa;

A.1、1     B.10、10     C.1、10     D.10、1

答案:B
解析:

A:申请数组空间,构造函数调用的次数就是数组的大小

B:正确

数组的大小就是C:申请数组空间,构造函数调用的次数就

D:如果释放数组空间,delete使用了[ ],则会对应的调用数组大小次数的析构函数


posted @ 2026-01-09 22:54  yangykaifa  阅读(6)  评论(0)    收藏  举报