iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++图文并茂分析讲解内存管理
  • 212
分享到

C++图文并茂分析讲解内存管理

2024-04-02 19:04:59 212人浏览 安东尼
摘要

目录1.了解一些基本的内存段(图演示)验证栈是向下生长的验证堆一般是向上生长的(不一定)巩固内存管理知识点答案2.c++申请动态内存的新玩儿法new,delete回顾C语言动态内存管

1.了解一些基本的内存段(图演示)

验证栈是向下生长的

#include<iOStream>
using namespace std;
int main()
{
	int a = 3;
	int b = 4;
	int c = 5;
	int d = 6;
	cout <<"a:"<< &a << endl;
	cout << "b:"<<&b << endl;
	cout << "c:"<<&c << endl;
	cout << "d:"<<&d << endl;
	return 0;
}

验证堆一般是向上生长的(不一定)

#include<iostream>
using namespace std;
int main()
{
	int num = 10;
	while (num--)
	{
		int *p1 = (int*)malloc(sizeof(int));
		int *p2 = (int*)malloc(sizeof(int));
		cout <<"p1"<< p1 << endl;
		cout <<"p2"<<p2 << endl;
		cout << endl;
		free(p1);
	}
	return 0;
}

一般情况下,p1的地址是比p2的地址高的(因为堆一般是向上生长的),但是有时候是不一定的。

巩固内存管理知识点

答案

温馨提示:题目中的指针是局部指针变量,是在栈上的,但是它指向的内容(解引用)可能是堆区或者常量区的。,可以画画图理解理解

2.c++申请动态内存的新玩儿法new,delete

回顾c语言动态内存管理的方式

malloccallocrealloc

  • malloc堆上动态开空间
  • calloc堆上动态开空间+初始化成0等价于malloc+memset
  • realloc指针已有的空间扩容

原题增容–后面又足够的空间

异地增容–后面没有足够的空间

开辟内置类型的空间

//C++开辟动态内存的新玩法
//语法演示:
#include<iostream>
using namespace std;
int main()
{
	//申请一个int的动态空间
	int* p1 = (int*)malloc(sizeof(int));
	*p1 = 1;
	int* p2 = new int(2);//这里是初始化
	free(p1);
	delete p2;
	//申请一个10各int的动态数组
	int *p3 = (int*)malloc(sizeof(int)* 10);
	for (int i = 0; i < 10; i++)
	{
		p3[i] = i + 1;
	}
	int *p4 = new int[10]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//初始化
	free(p3);
	delete[]p4;
	return 0;
}

跟c语言的版本相比,c++的版本,初始化时显得比较方便,而且语法比较简洁。当然了,更大的优越性还在后面。

开辟自定义类型的空间(请用vs2013以上版本测试代码)

#include<iostream>
using namespace std;
struct Listnode
{
	int _val;
	ListNode* _next;
	ListNode* _prev;
	//构造函数
	ListNode(int val = 0)
	:_val(val)
	, _next(nullptr)
	, _prev(nullptr)
	{
        cout<<"ListNode(int val = 0)"<<endl;
    }
	~ListNode()
	{
		cout << "ListNode()" << endl;
	}
};
int main()
{
	//申请一个结点的空间
    ListNode* pa = (ListNode*)malloc(sizeof(ListNode)*4);
	ListNode* pb = new ListNode(1);//不用去用sizeof去计算空间大小,很方便   
	free(pa);
	delete pb;
	//申请4个结点的空间--当然了一般不会这么玩儿,我们只是看看效果
	ListNode* pc = (ListNode*)malloc(sizeof(ListNode)* 4);
	ListNode* pd = new ListNode[4]{1, 2, 3, 4};
	free(pc);
	delete[]pd;
	return 0;
}

​ 学过c语言版本的数据结构的小伙伴都知道,我们push_back一个结点时,需要先实现一个buynewnode的函数(创建一个结点,并且对其进行初始化)。而new这个操作符,在创建结点的同时,已经帮我们实现了结点的初始化。调用了构造函数,而且delete还调用了析构函数。

总结一下

  1. c++中,如果是申请内置类型对象或者数组,mallocnew没有太大区别
  2. 如果时自定义类型,区别很大,new和delete时开空间+初始化,析构清理+释放空间,mallocfree仅仅时开空间+释放空间
  3. 建议在c++中,无论时内置类型还是自定义类型的申请释放,尽量使用new和delete。

3. 32位平台下可以开辟多大的内存

我:cpu过来遭罪

cpu:你不要过来啊

上述程序,我们开了1.8 G左右的内存,加上需要堆上的小内存,最后的综合有2 G的空间

如何开辟4G的内存

项目属性修改一下,改成64位平台即可,64位平台有2^34 G的空间(虚拟内存)在这我们不做细说,因为我也不太了解linux

4.了解operator new和operator delete

new其实是operator new + 构造函数

delete其实是operator delete+构造函数

newdelete是用户进行动态内存申请和释放的操作符,operator newoperator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间

大家可以将operator new和operator delete理解成和malloc 和free一样用法的函数。

唯一不同的地方是,operator new和malloc开辟空间失败的处理方式不一样,malloc是返回NULL空指针,而operator是抛异常,下面代码让大家看看效果,不必深究,以后会有介绍。

struct ListNode
{
	int _val;
	ListNode* _next;
	ListNode* _prev;
	//构造函数
	ListNode(int val = 0)
		:_val(val)
		, _next(nullptr)
		, _prev(nullptr)
	{
		cout << "ListNode(int val = 0)" << endl;
	}
	~ListNode()
	{
		cout << "ListNode()" << endl;
	}
};
void f()
{
	// 他的用法跟malloc和free是完全一样的,功能都是在堆上申请释放空间
	// 失败了处理方式不一样,malloc失败返回NULL,operator new失败以后抛异常
	ListNode* p1 = (ListNode*)malloc(sizeof(ListNode));
	free(p1);
	ListNode* p2 = (ListNode*)operator new(sizeof(ListNode));
	operator delete(p2);
	void* p3 = malloc(0x7fffffff);
	if (p3 == NULL)
	{
		cout << "malloc fail" << endl;
	}
	void* p4 = operator new(0x7fffffff);
	ListNode* p5 = new ListNode(2);
	cout << "继续" << endl;
}
//
//
int main()
{
	try
	{
		f();
	}
	catch (exception& e)
	{
		cout << e.what() << endl;
	}
	return 0;
}

malloc失败返回NULL,程序还会继续向下执行,但是operator new失败,就会报异常,f函数后面的没有在继续执行,然后走进catch语句中。

5.operator new和operator delete的类函数重载

struct ListNode//目的是提高效率
{
	ListNode* _next;
	ListNode* _prev;
	int _val;
	// 类中重载专属operator new
	void* operator new(size_t n)
	{
	void* p = nullptr;
	p = allocator<ListNode>().allocate(1);
	cout << "memory pool allocate" << endl;
	return p;
	}
	void operator delete(void* p)
	{
		allocator<ListNode>().deallocate((ListNode*)p, 1);
		cout << "memory pool deallocate" << endl;
	}
	ListNode(int val)
		:_next(nullptr)
		, _prev(nullptr)
		, _val(val)
	{}
};
int main()
{
	ListNode* p = new ListNode(1);
	delete p;
	return 0;
}

如果你自己在类里面写了operator newoperator delete,那么编译器就不会去调用系统提供的了,这是一种提高效率的方式。

我们是可以通过反汇编来看效果的

6.定位new–placement-new

通过上述的学习我们知道,malloc,和operator是不会去调用构造函数的,new会去调用构造函数,而且构造函数是只允许构造出对象时调用,而你的对象创建出来之后是无法调用构造的。

但是如果我们operator new了一块空间(未初始化),但是又想要调用其构造函数,该怎们办呢?

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a = 0)" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* pa = (A*)operator new(sizeof(A));
	//pa->A();//error错误调用方式,构造函数只允许构造时进行调用
	new(pa)A; // 定位new,placement-new,显示调用构造函数初始化这块对象空间
	A* pb = (A*)operator new(sizeof(A));
	new(pb)A(3);
    A* pc = new A;
	new(pc)A(3);
	// 等于 delete p
	pa->~A(); // 析构函数可以显示调用
	operator delete(pa);
	pb->~A();
	operator delete(pb);
    delete pc;
	return 0;
}

大家要知道定位new哦,他是一种对已经创建出来的对象,还能继续调用其构造函数的方式。

7.`malloc`/`free`和`new`/`delete`的区别

常考面试题

8.再次理解内存泄漏

首先大家先想一想这个问题:内存泄漏是指针丢了还是内存丢了?

内存管理中,内存是用指针去维护的,当你的动态内存空间还没有释放时,你已经把指针弄丢了,那么你将无法控制这段空间,进而导致内存泄漏。

什么是内存泄漏,内存泄漏的危害

什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而 造成了内存的浪费。

内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会 导致响应越来越慢,最终卡死。

到此这篇关于C++图文并茂分析讲解内存管理的文章就介绍到这了,更多相关C++内存管理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++图文并茂分析讲解内存管理

本文链接: https://www.lsjlt.com/news/167656.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++图文并茂分析讲解内存管理
    目录1.了解一些基本的内存段(图演示)验证栈是向下生长的验证堆一般是向上生长的(不一定)巩固内存管理知识点答案2.c++申请动态内存的新玩儿法new,delete回顾c语言动态内存管...
    99+
    2024-04-02
  • C++图文并茂分析讲解模板
    目录1.内容引入2.模板函数C语言写交换函数C++写交换函数模板交换函数的语法及其原理语法原理理解显示实例化和隐式实例化关于编译器也是懒人这件事3.类模板1.内容引入 ​ 不知道大家...
    99+
    2024-04-02
  • C++图文并茂讲解继承
    目录一、生活中的例子二、惊艳的继承三、继承的意义四、小结一、生活中的例子 组合关系∶整体与部分的关系 下面看一个组合关系的描述代码: #include <iostream&g...
    99+
    2024-04-02
  • SpringBoot图文并茂讲解依赖管理的特性
    目录1.父依赖parent介绍2.修改默认版本号3.starter场景启动器1.父依赖parent介绍 pom文件中含有父依赖 <parent> ...
    99+
    2024-04-02
  • Mybatis图文并茂讲解分页插件
    目录1. Mybatis分页插件1.1 分页插件介绍1.2 分页插件的使用1.3 分页插件的参数获取1.4 分页插件知识小结1. Mybatis分页插件 1.1 分页插件介绍 分页...
    99+
    2024-04-02
  • C语言图文并茂讲解分支语句用法
    目录一、if 语句分析二、switch 语句分析三、小结一、if 语句分析 if 语句用于根据条件选择执行语句else 不能独立存在且总是与它最近的 if 相匹配else 语句后可以...
    99+
    2024-04-02
  • C++图文并茂讲解类型转换函数
    目录一、类型转换函数(上)1.再论类型转换2.问题3.再论构造函数4.另一个视角5.编译器的行为6.小结(上) 二、类型转换函数(下)1.类型转换2.编译器的行为3.注意事...
    99+
    2024-04-02
  • 图文并茂地讲解Mysql索引(index)
    目录前言1. 索引概述1.1 什么是索引?1.2 使用索引和不使用索引的区别1.3 索引的特点2. 索引结构2.1 概述2.2 二叉树2.3 B-Tree2.4 B+Tree2.5 ...
    99+
    2022-11-13
    mysql怎么使用索引 mysql的索引 mysql索引代码
  • 图文并茂讲解RocketMQ消息类别
    目录1、同步消息2、异步消息3、单向消息1、同步消息 即时性较强,重要的消息,且必须有回执的消息,例如短信,通知(转账成功) 生产者: public class Producer ...
    99+
    2022-12-27
    RocketMQ消息类别 RocketMQ消息类型
  • C/C++深入讲解内存管理
    目录C/C++内存分布C语言中的动态内存管理C++的内存管理operator new与operator delete函数operator new与operator dele...
    99+
    2024-04-02
  • SpringBoot图文并茂讲解登录拦截器
    目录1.相关概念1.实现效果2.实现步骤2.代码实现1.配置文件2.java代码3.前端代码3.运行测试1.相关概念 1.实现效果 当没有输入正确的账号密码登录成功时, 除了登录页,...
    99+
    2024-04-02
  • C语言动态内存分配图文讲解
    目录思维导图1.为什么存在动态内存分配2.动态内存函数的介绍2.1 malloc2.2 free2.3 calloc2.4 realloc3.常见的动态内存错误思维导图 1.为什么...
    99+
    2023-01-17
    C语言动态内存分配 C语言动态内存分配函数
  • C++ 内存管理原理分析
    目录1.C/C++中程序内存分布1.1 内存分布图1.2 小试牛刀2.C语言部分的动态内存管理方式3.C++内存管理方式3.1new/delete操作内置类型3.2 new...
    99+
    2024-04-02
  • C/C++指针与内存管理图文详解
    目录一.指针二.数组总结指针和内存管理始终是C/C++比较容易模糊的知识点,但在C/C++编程中又绕不开的地方,特别在下位机上,会频繁的与指针打交道,如果概念模糊,一不小心就会写出冗...
    99+
    2024-04-02
  • C#内存管理举例分析
    本篇内容主要讲解“C#内存管理举例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#内存管理举例分析”吧!C#内存管理C#内存管理提供了与java一样的自动内存管理功能,让程序员从繁重的内存...
    99+
    2023-06-17
  • MyBatis图文并茂讲解注解开发多对多查询
    目录MyBatis的注解实现复杂映射开发多对多查询多对多查询的模型多对多查询的语句添加CourseMapper 接口方法使用注解配置Mapper测试类多对多配置总结MyBatis的注...
    99+
    2024-04-02
  • MyBatis图文并茂讲解注解开发一对一查询
    目录MyBatis的注解实现复杂映射开发一对一查询一对一查询的模型一对一查询的语句创建PersonMapper接口使用注解配置Mapper测试类一对一配置总结MyBatis的注解实现...
    99+
    2024-04-02
  • C/C++内存管理的示例分析
    这篇文章主要介绍了C/C++内存管理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。C/C++赋予程序员管理内存的自由,是C/C++语言特色,虽然这引入了复杂度和危险...
    99+
    2023-06-15
  • C语言详细分析讲解内存管理mallocreallocfreecalloc函数的使用
    目录C语言内存管理一、动态空间申请二、动态空间的扩容三、释放内存C语言内存管理 malloc && realloc && free &&...
    99+
    2024-04-02
  • MyBatis图文并茂讲解注解开发一对多查询
    目录MyBatis的注解实现复杂映射开发一对多查询一对多查询的模型一对多查询的语句创建StudentMapper接口使用注解配置Mapper测试类一对多配置总结MyBatis的注解实...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作