IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++面向对象核心编程必备知识点之----堆区 -> 正文阅读

[C++知识库]C++面向对象核心编程必备知识点之----堆区

目录

1.堆区概念

2.new的基本语法

2.1相应类型指针变量进行接收

2.2非对应类型指针变量进行接收(会报错)

2.3不用指针变量接收(结果?)

?2.4直接解指针输出new内容(结果?)

3.delete释放new开辟出的内存

3.1delete在普通变量中的的用法(释放单个空间)

3.2delete释放数组的用法(释放多个连续空间)

4.总结和注意事项


1.堆区概念

c++中内存有四个区,分别是代码区,全局区,栈区,堆区
(1)代码区顾名思义就是内存中用来存放代码的区域,具有共享性(减少同时运行两次程序产生复制,造成不必要的资源浪费)和只读性(防止程序运行过程中代码被不经意修改)
(2)全局区用来存放全局变量、静态变量、常量、字符串常量、counst修饰的全局变量(全局常量)
(3)栈区用来存放局部变量,函数参数等,栈区数据的注意事项---不要返回局部变量的地址,栈区的数据由编译器管理和释放
(4)堆区是由开发人员决定的,由我们进行释放,若不释放程序结束后编译器自动释放,可以用new关键字进行开辟内存,用delete释放所开辟的内存

2.new的基本语法

2.1相应类型指针变量进行接收

new关键字用于在堆区中申请内存时,有着一定的语法规则

? ? //在堆区创建整型数据,就用整型指针接收
?? ?//new返回是该数据类型的指针

#include<iostream>

using namespace std;

int main()

{

? ?int * p = new int((10));

? ??float * b=new float((35.12f));

????cout<<*p<<endl;

? ? cout<<*b<<endl;

? ? system("pause");

? ? return 0;

}

分别输出int整型指针变量p的内容和float单精度浮点型指针变量b的内容

结果如下图所示:

可以正常输出

2.2非对应类型指针变量进行接收(会报错)

试着用float类型指针接收开辟的int内存

int main()
{
    float * p = new int((10));
    int * b = new float((35.12f));
    cout << *p << endl;
	cout << *b << endl;

	system("pause");
	return 0;
}

?产生了错误,提示是:int 类型的值不能用于初始化float类型的实体

从这个报错内容可以看出:01.new返回的同类型的指针,要用同类型指针接收new出来的数据

2.3不用指针变量接收(结果?)

如果不对new的内容进行接收,能输出么?

int main()
{
	cout << "没有进行接收的new数据输出"<< new int((10)) << endl;
    int * p = new int((10));
    float * b = new float((35.12f));
    cout << *p << endl;
	cout << *b << endl;

	system("pause");
	return 0;
}

输出结果是一串地址,也间接说明了new关键字开辟出的是地址,既然是地址,就要用指针来接收,上一步验证过了要用同类型的对应指针型变量来接收,并且解指针后输出相应内容

?2.4直接解指针输出new内容(结果?)

那么直接用*解指针new出的内容呢?

int main()
{
	/*int *p = func();
	test01();
	test02();*/
	cout << "没有进行接收的new数据输出"<< new int((10)) << endl;
	cout << "解指针new数据输出" << *(new int((10))) << endl;
    int * p = new int((10));
    float * b = new float((35.12f));
    cout << *p << endl;
	cout << *b << endl;

	system("pause");
	return 0;
}

从输出结果与之后的用指针型变量来接收的结果来看,是一样的,所以,直接输出解指针new的数据可行,但是为啥不常用呢,从个人角度来看,可读性不高且不够美观,所以不常用,习惯性用相应类型指针变量接收再解指针输出,显得更直观些

3.delete释放new开辟出的内存

释放内存两种方式:
new <--> delete
new [] <--> delete []

3.1delete在普通变量中的的用法(释放单个空间)

对于普通变量,比如以下,可以在该变量之前加入delete关键字直接进行释放

p 是指向动态分配的内存的指针

int main()
{
	int *p = new int(10);
	cout << *p << endl;
	delete p;//释放
	cout << *p << endl;//释放了之后能正常输出么?


	system("pause");
	return 0;
}

引发了异常,访问权限

换句直白点的比喻就是说,你手上有100REN,拿去吃了顿饭,把100REN给了饭店老板,相当于这个100REN已经被你释放了,时候再问老板要,人家会给你么,这就产生了100REN的归属权,释放了100REN之后,那个100REN已经不属于你的私人财产范围了,你去染指,那就是超出了你的访问权限,属于非法访问,我们的编译器还是很公道的,不允许违法乱纪

3.2delete释放数组的用法(释放多个连续空间)

如果我们按照释放普通变量(释放单个空间)的方法释放数组,会是怎样的?

int main()
{
	int * arr = new int[10];//new一个10个元素的数组arr,用int类型指针arr接收
	for (int i = 0; i < 10; i++)
	{
		arr[i] = i + 100;//给每个数组元素赋值,范围是100~109
	}
	//输出arr[i]
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << endl;
	}
	delete arr;//按照3.1方法释放数组

	system("pause");
	return 0;
}

结果如下,虽然可以正常输出,但其实数组并没有被释放

如果动态分配了一个数组,但是却用delete p的方式释放,没有用[],则编译时没有问题,运行时也一般不会发生错误,但实际上会导致动态分配的数组没有被完全释放。

牢记,用 new 运算符动态分配的内存空间,一定要用 delete 运算符释放。否则,即便程序运行结束,这部分内存空间仍然不会被操作系统收回,从而成为被白白浪费掉的内存垃圾。这种现象也称为“内存泄露”。

如果一个程序不停地进行动态内存分配而总是没有释放,那么可用内存就会被该程序大量消耗,即便该程序结束也不能恢复。这就会导致操作系统运行速度变慢,甚至无法再启动新的程序。但是,只要重新启动计算机,这种情况就会消失。

编程时如果进行了动态内存分配,那么一定要确保其后的每一条执行路径都能释放它。

另外还要注意,释放一个指针,并不会使该指针的值变为 NULL。

在释放new数组时,应该告诉编译器释放的是数组类型的arr,一一对应,不仅能达到真正的释放多个连续空间,也能增加代码健壮性

在arr 前面加[]中括号

int main()
{
	int * arr = new int[10];//new一个10个元素的数组arr,用int类型指针arr接收
	for (int i = 0; i < 10; i++)
	{
		arr[i] = i + 100;//给每个数组元素赋值,范围是100~109
	}
	//输出arr[i]
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << endl;
	}
	//delete arr;
	delete[] arr;
    arr=NULL;//把释放后的指针置为NULL,这里不用加中括号


	system("pause");
	return 0;
}

4.总结和注意事项

new delete使用时注意以下几点

1.当传入的形参是数组时,能加const的就加const,防止在函数内部中的意外操作
2.内存new和delete时,原则:谁申请谁释放
3.在delete指针后,将指针置为NULL。例如:delete p; p = NULL;?

这样可以避免出现以下现象:

1.执行delete语句时,程序直接弹窗,崩溃
2.执行delete语句时,程序卡死。将delete语句注释掉,又正常了,但发生了内存泄露

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:06:35  更:2022-11-05 00:11:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 6:40:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码