参考:https://www.cnblogs.com/shilinnpu/p/8873271.html
c++的内存分为
1.全局和静态存储区(.data segment和.bss segment)
全局和静态被分配到一块内存里
在c里面
bss(Block Started by Symbol以符号开始的块):.bss保存只有声明没有初始化的全局变量
.data 数据段:一般存放已经初始化的全局变量
现在c++里面已经不分了
2.常量存储区(.rodata segment)
存放常量,不能修改
3.堆heap
用户自己管理的动态内存,如果用户不释放,程序结束后,os回收
new运算符
可以确保调用对象的构造函数之前,堆内存是开辟成功的,new操作符返回一个指向类对象的指针,delete删除内存,没有删除会造成内存泄漏
Person* p=new Person();
malloc(函数)
不会调用构造函数,只能确定开辟内存的大小,不能确定里面是否有垃圾数据,返回void*,free删除内存
malloc(sizeof(int));
4.栈stack
- 编译器自动分配
- 存放局部变量,函数参数值
- 存放在栈中的数据只在当前函数及下一层函数中有效,一旦函数返回了,这些数据也就自动释放了。
每当一个函数被调用,这个函数的地址和一些关于调用的信息(比如某些寄存器的内容)就会被储存到栈区
然后这个被调用的函数再为它的自动变量和临时变量在栈区上分配空间,这就是C实现 函数递归调用的方法。每执行一次递归函数调用,一个新的栈框架就会被使用,这样这个新实例栈里的变量就不会和该函数的另一个实例栈里面的变量混淆。
5.代码区(.text)
编译后的函数,机器码
Linux下,程序在内存里的分布:
按程序在内存中驻留的时间分
1静态内存
包含 局部静态变量 当经过初始化语句被加载进内存,直到程序结束
类静态数据成员 类内静态变量
类内静态函数
定义在任何函数之外的变量(全局变量)
2动态内存
我们常说的heap内存,每一个程序都有一个内存池,这部分被称为自由空间即堆内存,动态对象的生命周期由程序决定
3栈内存
仅在定义的程序块内有效,由编译器自动创建和销毁
智能指针
对动态内存的管理很麻烦,如果new后没有delete,就会造成内存泄漏,非法内存(浅拷贝,对同一块内存释放两次)
c++11新标准提供了两种 智能指针 smart pointer 类型来管理对象
粗理解
传入一个对象的指针给智能指针 例如 People* p,把这个指针p托管给智能指针,智能指针析构的时候对p指向的内存进行释放
shared_ptr允许多个指针指向同一个对象
unique_ptr 独占指向的对象
weak_ptr是shared_ptr伴随类,它是一种弱引用,指向shared_ptr所管理的对象
shared_ptr,unique_ptr,weak_ptr都是定义在memory头文件中
shared_ptr类
智能指针也是一种模板,所以当我们创建智能指针时,必须额外提供一个信息-----指针可以指向的类型
shared_ptr<string> p1 p1可以指向string类型的对象
shared_ptr<list<int>> p2 p2可以指向int的list的对象
默认初始化的智能指针里包含一个空指针
shared_ptr和unique_ptr都可以有的操作
- shared_ptr<T> sp 空智能指针,可以指向类型为T的对象
- unique_ptr<T> up
- p 将p作为一个判断对象,若p指向一个对象,则为true
- *p 解引用P,获得它指向的对象
- p->men 等价于(*p).men
- p.get() 返回p中保留的指针。若智能指针释放了对象,返回的指针所指向的对象也就消失了
- swap(p,q)交换p和q中的指针
- p.swap(q)
shared_ptr独有的操作
make_ptr<T>(args) 返回一个shared_ptr,指向一个动态分配的类型为T的对象,使用args初始化这个对象
shared_ptr<T>p(q) p是shared_ptr的拷贝,q的计数器+1,q中的指针必须能转化成为T* ,就是说q中的指针所指向的对象一定能转换可以传换成T的类型 X=T X*=>T*
p=q p和q都是shared_ptr,所保存的指针必须能互相转化,递减p的引用次数,递增q的引用次数,如p减为0,将其管理的内存释放
p.unique() 若