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++内存管理(一)---->new和delete -> 正文阅读

[C++知识库]C/C++内存管理(一)---->new和delete

主要内容:

  • C/C++内存布局
  • new和malloc的区别
  • delete和free的区别

C/C++内存布局
C/C++内存分为如下的几个部分:

1.栈区 存放临时的局部变量
2.堆区 malloc,realloc,calloc申请的动态内存
3.静态区 存储全局变量和局部静态变量
4.常量区(代码段) : 存储常量的区域

首先我们要知道为什么要对内存区域进行划分。最重要的一个原因就是为了方便管理数据,因为计算机世界最重要的资源就是数据。对于数据更好 的管理就显得十分有必要!而划分内存区域就是这样的一种手段。
来看一看下面这些变量分别存储在什么地方:

 #define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
static int g_val = 10;
void exam()
{
	static int s_val = 20;
	int val = 5;
	char arr[] = "hello world";
	const char* pa = "hello world";
	int* a = (int*)malloc(sizeof(int) * 5);
	free(a);
}
int main()
{   
	exam();
	return 0;
}

g_val ,s_val ,val在什么区域?
arr在哪个区域,*arr在什么区域?
p在哪个区域,*p在哪个区域?
a在哪一个区域,*a在哪个区域?

答案是:g_val ,s_val在静态区,arr,*arr在栈区
p在栈区,*p在常量区 , a在栈区,a在堆区

可能比较容易出错的就是arr和arr这两个地方

char arr[]="abcdef";
//abcdef是一个常量字符串,本身是在静态区,但是这段语句的意思是创建一个数组,把常量字符串"abcdef"的内容拷贝到这个数组里面,所以这个数组本质还是在栈上的!

了解了这个C/C++的内存布局,接下来我们来看new和malloc的区别。


new和malloc的区别
首先,我们知道C++兼容C语言,也就是C语言那套内存管理机制我们在C++里面仍然还可以继续使用。但是C++又引入了自己的新机制—>new关键字来替代malloc,那么new和malloc究竟有什么区别。new又应该怎么使用呢?

//new的使用
void test()
{   //动态申请一个int类型的对象
	int* p = new int;
	//动态申请一个能够存放10个int的数组
	int* pa = new int[10];
	//和第二个区别,这个只申请了一个int类型对象,这个对象的值被初始化成10
	int* ppa = new int(10);
}

在这里插入图片描述
那么这时候不难可以看出。这里的new和malloc并没有太大的区别,确实是这样!对于内置类型来说,使用new和使用malloc几乎没有区别。真正不同的地方是在于对于自定义类型的处理!

class A
{ 
  public:
	A(int a=0)
	:_a(a)
    {}
  private:
	int _a;
};
//new和malloc的区别--->自定义类型
void show()
{
	//使用malloc创建A类成员
	A* pa = (A*)malloc(sizeof(A));
	//使用new来创建A类成员
	A* ppa = new A;
}

在这里插入图片描述
从调试窗口不难可以看出,malloc只是申请了一块空间,对于空间里面的内容不做任何处理!而new在申请空间的同时,还还调用了构造函数!所以对于自定义类型来说,new会在申请空间的同时调用构造函数初始化! 那么接下来我们用一个实例体会new带来的好处。

//使用new来创建带头双向循环链表
struct ListNode
{
	int _val;
	ListNode* _prev;
	ListNode* _next;
	//写好ListNode的构造函数
	ListNode(int val=0)
		:_val(val)
		,_prev(nullptr)
		,_next(nullptr)
	 {}
};
class List
{ public:
	List()
	{ //自动就会调用ListNode的构造函数(这里是默认构造)
		_head = new ListNode;
// _head=new ListNode();--->这种写法也可以,不推荐!(严格和Java的写法区分开来!)
			
		_head->_prev = _head;
		_head->_next = _head;
	}
	~List()
	{
		ListNode* cur = _head->_next;
		while (cur != _head)
		{
			ListNode* next = cur->_next;
			delete cur;
			cur = next;
		}
		delete _head;
		_head = nullptr;
	}
 private:
	 ListNode* _head;
};
int main()
{
   List L;
   return 0;
}

我们只要在main里面写这样一个语句就可以创建一个带头双向循环链表了!相比于先前使用C语言写一大堆冗余的函数来进行工作,一个new就为我们不少的问题。
顺便补充一下,使用vs开发的时候,vs会强制性检查malloc,realloc,calloc动态开辟以后返回的指针的合法性,而使用new就不会检查,因为new失败以后不是返回空指针,而是会抛出异常。关于异常,我会在后续的博客内容中介绍,这里只要了解一下new失败是抛出异常就可以了。


2.delete和free的区别
C++也提供了特定的内存释放的方式---->delete,那么首先我们先来看一看delete是怎么使用

//delete的使用
int main()
{  //申请1个int的空间 
   int* p=new int;
   //释放p所指向的1个int的空间
   delete p;
   //申请10个int的空间
   int* pp=new int[10];
   //释放pp指向的连续空间
   delete[] pp;
   return 0;
}

注意:new就要和delete配对!malloc,realloc,calloc就要和free一起!new数组就要用delete[]释放 。不要混着乱用!乱用可能有的时候不会出错,但是多数情况下可能会导致程序崩溃!
那么和C++引入new一样,C++引入delete来管理内存的释放肯定是有delete的独到之处的,我们不妨来看一下经典的MyQueue类,看看free和delete一个MyQueue对象是一种什么样的场景:

class Stack
{
public:
	Stack(int capacity=4)
		:_a(new int[capacity])
		,_size(0)
		,_capacity(capacity)
	{}
	~Stack()
	{
		delete[] _a;
		_a = nullptr;
	}
private:
	int* _a;
	size_t _size;
	size_t _capacity;
};
class MyQueue
{
private:
	Stack _pushst;
	Stack _popst;
};
int main()
{   MyQueue* p=new MyQueue;
    delete p;
   return 0;
}

在这里插入图片描述
此时还没执行delete,单步按下F11进入下一步调用的函数内部
在这里插入图片描述
可以看到,delete并不是直接就把p指向的那块空间释放了,而是先调用了析构函数清理资源!最后清理完资源以后才会释放p指向的空间!而如果是free,free就只会释放当前指针指向的那块空间,极大可能会造成内存泄漏!


总结

  • new不仅会申请空间,还会调用构造函数
  • delete在释放指针指向空间之前,会先调用析构函数清理资源。

文章主要内容就到这里,希望大家可以共同进步。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 22:37:15  更:2022-07-04 22:38:32 
 
开发: 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年11日历 -2024/11/23 16:57:23-

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