C++ 内存管理深入学习总结笔记(详细)

36 篇文章 0 订阅
1.1 为什么研究内存管理
1.1.1 程序:数据 + 算法
  1. 写程序是为了解决某个问题,生活中的问题最终被计算机抽象为控制或运算
  2. CPU中的主要构件就是运算器和控制器,本质上是一堆组合逻辑电路,表现为机器指令集
  3. 一个问题对应一个程序,一个程序分为多个函数,一个函数分为多个机器指令
  4. 存储机器指令需要内存,机器指令的执行过程需要内存参与,这是内存的2大作用
  5. 算法对应机器指令(ROM内存),数据对应RAM内存,CPU对应工作机器
  6. 越是偏底层的语言,越对内存管理具体化,效率也越高,同时对编程者要求也越高
1.1.2 计算机中如何管理内存
  1. C++项目大多数对应在操作系统中运行,很少有裸机
  2. OS提供最基本的内存管理体系,OS直接管理物理内存,并向应用层提供一套内存接口
  3. C++语言对OS的内存接口进行封装,提供给编程者一套内存使用方法
  4. 编程人员写的代码在编译工具链、运行时、OS等体系的帮助下最终在计算机物理层运行
1.1.3 总结
  1. 内存管理的原理虽然庞大而复杂,然而程序员只需要掌握好C++语言的内存管理语言特性即可
  2. C++程序容易出bug,主要就是因为内存管理部分的复杂性
  3. Java,python等语言提供了更多的封装,所以降低了程序员操作难度和犯错可能性
1.2 C++ 可用内存区域
1.2.1 C语言可用内存区域
  1. 栈,对应局部变量
  2. 全局数据区/静态数据区,对应全局变量,静态局部变量
  3. const数据区,在内存层面是不存在的,是C编译器营造出来的
  4. 代码段,放可执行程序的,性质是rom
  5. 堆heap,由malloc和free来管理的一块内存
1.2.2 C++新增内存区域
  1. 自由存储区,由new申请得到的动态内存区域
  2. new操作符使用举例
#include <iostream>
using namespace std;

int a;		// a分配在全局数据区

int main(void)
{
	int b;	// b分配在栈上面
	// a分配在heap中,指针p指向a,指针p自身分配在栈上
	int *p = (int *)malloc(4);
	*p = 5;	// 使用p指向的4个字节内存
	free(p);// 释放p指向的4个字节内存

	// c++中使用new和delete替代malloc和free
	int *q = new int;	// q本身分配在栈上,q指向的是一个int类型的数,占4个字节
						// 这4个字节分配在自由存储区
	*q = 5;				// 使用q指向的4个字节内存
	cout << "q = " << q << ", " << "*q = " << *q << endl;
	delete p;			// 释放q指向的4个字节内存

	return 0;
}
1.2.3 总结
  1. 代码段只会读不会写,一般不会出任何问题
  2. 全局数据区和栈区都是自动管理的,只要可用内存足够不会出问题
  3. const数据区实际上是由编译器来保证只读的,本质就是普通的内存区域
  4. 灵活性和风险都集中在heap区域,常见问题如内存泄漏、内存碎片等
1.3 new和malloc的区别
1.3.1 简单区别
  1. malloc是C库函数,new是C++运算符关键字
  2. malloc申请空间大小靠传参确定,而new不需要传参,对象本身大小由编译器自动计算给出
  3. malloc返回值为void *因此需要强转,而new返回值类型为确定的对象指针类型
  4. malloc对应free释放,new对应delete和delete[]释放
1.3.2 深度区别
  1. malloc只能申请内存不能带初始化,而new可以带初始化
  2. new会执行类的构造函数而malloc不会
  3. malloc失败返回NULL,而new失败引发bad_alloc异常
  4. 申请和释放数组类型时不同
1.3.3 总结
  1. linux平台中new内部是通过malloc实现的,new比malloc多一个调用构造函数
  2. malloc只是返回一块荒地给你,而new会给你修好路盖好房子规划好田地等
1.4 智能指针的引入
1.4.1 指针的优势和劣势
  1. 指针的本质是一个变量,变量的值是其他对象的地址,因此可以解引用
  2. 指针本质上对应CPU指令中的间接寻址,所以指针是天然存在的,是CPU设计决定了的
  3. 指针的优势就是灵活、代码效率高
  4. 指针的劣势是太灵活,尤其结合动态内存和构造、析构后,在复杂业务中容易出错
1.4.2 如何解决
  1. 底层不用指针是不可能的,因此这个问题是绕不开的
  2. 解决方案1:由程序员来自主把控,C/C++典型编程就是这样
  3. 解决方案2:由程序员和专门设计的自动管理机制共同把控,典型代表是智能指针
  4. 解决方案3:由自动管理机制全权把控,程序员不用管,典型代表是Java的垃圾回收机制
1.4.3 智能指针如何实现
  1. 将普通的简单纯指针封装为栈式复合指针对象,即智能指针对象
  2. 智能指针本身定义为局部变量,分配在栈内存上,因此本身是自动回收的
  3. 智能指针内部设计为当智能指针本身要被弹栈释放时,执行事先挂接好的清理函数
  4. 智能指针的正常使用通过一些提供的方法和运算符重载来使用
1.4.4 智能指针总结
  1. 智能指针是普通指针的升级版,封装版,本身具备指针的功能,且多出一些自动释放资源机制
  2. 智能指针进行动态内存管理,要比普通指针多出很多(内存和性能上的)开销
  3. 智能指针的实现不是唯一的,C++有很多智能指针,各有优劣和适用场景,如:std::auto_ptr、boost::scoped_ptr、boost::shared_ptr、boost::scoped_array、boost::shared_array、boost::weak_ptr、boost::intrusive_ptr
  4. 智能指针也要按照设计去正确使用,否则也会出问题
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值