一般程序C++程序的内存分为三个部分:
- 静态内存:静态内存空间用来保存局部static对象、类static数据成员以及定义在函数之外的变量。静态区的内容在整个程序的生命周期内都存在,使用之前分配,在程序结束时销毁。
- 栈内存:栈内存用来保存定义在函数内的非static对象。对于栈对象,仅在其定义的程序块运行时才存在,当程序块运行结束时自动销毁。
- 自由空间或堆内存:由malloc系列函数或者new操作符分配的内存。其生命周期由free和delete决定。在没有释放之前一直存在,直到函数结束。
new/delete
在C++中,new/delete运算符用来管理动态内存的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化;delete,接收一个动态内存对象的指针,销毁该对象,并释放与之关联的内存。
使用new动态分配初始化对象
在自由空间分配的内存是无名的,因此new无法为其分配的对象命名,而是返回一个指向该对象的指针。
//未初始化
int *pi = new int;
string *ps =new string;
//初始化
int *pi = new int(1024);
string *ps = new string(10,'9');
const int *pci = new const int(1024);
vector<int> *pv = new vector<int>{0,1,2,3,4,5,6,7,8,9};
//值初始化
string *pi = new string();
int *ps = new int();
//p1指向一个与pi类型相同的对象
auto p1 = new auto(pi);
释放动态内存
为了防止内存耗尽,在动态内存使用完毕后,必须将其归还给系统。我们通过delete表达式(delete expression)来将动态内存归还给系统。delete表达时式接收一个指针,指向我们想要的释放的对象。
delete pi;
delete ps;
//释放一个const对象
delete pci;
delete 表达式也执行两个动作:销毁给定的指针指向的对象;释放对应的内存。我们传递delete的指针必须指向动态分配的内存,或者是一个空指针。虽然一个const对象的值不能被改变,但它本身是可以被销毁的。
在指针被delete之后,指针就变成了空悬指针,即:指向一块曾经保存数据对象但现在已经无效的内存指针。如果我们需要继续保留指针,有如下的方法,这样就可以清楚指出指针不指向任何对象。
int *p(new int(42); //p指针指向动态内存
auto q = p;
delete p; //p和q均无效
p = nullptr;
shared_ptr和new结合使用
我们平时在使用动态内存很容易出现问题的,C++为了我们更安全的、更容易地使用动态内存,在新标准库memory提供了两种智能指针类型来管理动态对象:shared_ptr允许多个指针指向同一个对象;unique_ptr则“独占”所指向的对象。标准库还定义一个名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象。
shared_ptr<int> p1 = new int(24); //错误:不能将一个内置指针隐式转换智能转换
shared_ptr<int> p1(new int(42)); //正确:必须使用直接初始化形式
由于智能指针参数的构造函数是explicit的,因此,我们不能进行内置指针到智能指针间的隐式转换。出于相同的原因,一个返回shared_ptr函数不能在其返回语句中隐式转换一个普通指针。
shared_ptr<int> clone(int p)
{
return shared_ptr<int>(new int(p));
}
malloc/free(https://www.cnblogs.com/maluning/p/7944231.html#_label1)
malloc/free是C语言的标准库函数,函数原型:(void*)malloc(unsigned size);(字节数),在头文件stdlib.h中声明。
malloc函数在内存中开辟的是一块连续的空间,size是所需要空间的长度,开辟的大小为size*参数类型,开辟完之后返回这块空间的首地址,分配内存后必须验证内存是否分配成功,当完成之后new函数对内存进行释放。
int *p =(int *) malloc(int);
if(p==NULL)
cout<<"Out of memory!"<<endl;
free(p);