一、三大内存区域
栈内存:保存定义在函数内的非static对象。
静态内存:保存局部static对象,类static数据成员以及定义在任何函数之外的变量。
堆(自由空间):存储动态分配的对象。
程序使用动态内存出于以下三种原因之一:
1、程序不知道自己需要使用多少对象
2、程序不知道所需对象的准确类型
3、程序需要在多个对象间共享数据
二、动态内存与智能指针
头文件:memory
1、运算符new、delete
new:在动态内存中为对象分配空间并返回一个指向对象的指针。
delete:接收一个动态对象的指针,销毁对象,并是释放与之关联的内存。
2、shared_ptr类
每个shared_ptr都有一个关联的计数器,称为引用计数。该计算器记录了一个对象被多少个智能指针指向。shared_ptr的析构函数会递减它所指向的对象的引用计数。如果引用计数变为0,shared_ptr的析构函数就会销毁对象,并释放
执行delete运算符后,先调用对象的析构函数,后释放内存
指定d(替代delete)后,在对象应该释放时将调用d(即使原来有析构函数,也是调用d而不调用原始函数),在d中需要使用delete运算符释放内存。
shared_ptr sp(new testClass("123"),f);
(1)当对象的引用计数为0,但有其他指针指向它时,该对象是否会被销毁?
答:会销毁
(2)make_shared函数
最安全的动态内存分配方法是调用make_shared的标准库函数。此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。
shared_ptr p1 = make_shared();
auto p2 = make_shared("CDA");
3、unique_ptr类
某个时刻只能有一个unique_ptr指向一个给定对象,当unique_ptr被销毁时,它所指向的对象也被销毁。
因为某时刻只能一个unique_ptr指向一个给定对象,所以不能拷贝unique_ptr,但是有一个例外,我们可以拷贝或赋值一个将要被销毁的unique_ptr。例如:
注:
向unique_ptr传递删除器
unique_ptr<对象类型,删除器类型> p(new 对对象类型,删除器);
(1)能否让一个unique_ptr和一个shared_ptr指向同一个对象
运行时发生错误。
结论:unique_ptr指向一个对象后,便不能再有智能指针指向该对象。
4、weak_ptr
weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就被释放。即使有weak_ptr指向对象,对象也还是会被释放。
由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock。
weak_ptr wp(make_shared("123"));
5、使用规范
delete内存后将指针赋值为nullptr,表示指针不再绑定到任何对象