- 内存分配方式
(1)从静态存储区域分配。内存在编译的时候就已经分配好了,在整个程序执行运行期间一直存在。如:全局变量,static变量。
(2)在栈上创建。在执行函数时,函数内部的局部变量的存储单元在栈上创建。函数执行结束后局部变量的存储单元自动释放。
(3)在堆上创建。也称动态内存分配。程序在运行的时候用new或malloc申请任意的内存,程序员自己负责何时用delete或free释放内存。
- 我们都知道c语言开辟以及释放空间用malloc和free。而在c++中却用new和delete。。
这是为什么呢?
首先,malloc和free是c/c++语言的标准库函数。而new和delete是c++的运算符。它们都是用来动态开辟内存和释放内存。
对于对象而言,光用malloc和free无法满足动态对象的要求。对象在创建的同时要执行构造函数初始化对象,在消亡之前要调用析构函数清理对象。由于malloc和free是库函数不是运算符,不能够把执行构造函数和析构函数的任务强加到malloc和free。
所以c++语言需要一个能够完成动态内存分配和初始化工作的运算符new,以及一个清理和释放内存工作的运算符delete。
注:new和delete不是库函数,是运算符。
3. malloc/free与new/delete的联系
(1)动态内存管理的入口
(2)malloc和free是c/c++语言的标准库函数。而new和delete是c++的运算符。
(3)malloc/free动态开辟空间及释放,new/delete动态开辟空间调用构造函数初始化,清理内存之前调用析构函数。
(4)malloc/free手动计算类型大小,返回void *,而new/delete自动计算类型大小,返回对应类型的指针。
4.new和delete
(1)
p1:开辟了一个整型空间
p2:开辟了一个整型空间,并初始化为100.
注:new运算符实际上调用了 operator new()函数,而operator new()函数中又调用了malloc函数。
delete运算符实际上调用了operator delete()函数。而operator delete()函数又调用_free_dbg()函数。
(2)
p3:开辟了10个整型空间
调用10次构造函数以及10次析构函数。
注:new运算符实际上调用了 operator new[]()函数。operator new[]()函数调用了 operator new()函数,而operator new()函数中调用了malloc函数。
delete运算符实际上调用了operator delete[]()函数。operator delete[]()函数调用了operator delete()函数,而operator delete()函数又调用_free_dbg()函数。
注:malloc/free,new/delete, new[]/delete[]必须匹配,否则内存泄露,程序崩溃。
c++的其他内存管理接口:
void *operator new(size_t size)
void operator delete(size_t size)
void *operator new[](size_t size)
void operator delete[](size_t size)
5.定位new表达式
在已分配的原始空间上调用构造函数初始化。
new (place_address) type
new (palce_address) type (initializer-list)
place_address必须是一个指针,指向已经分配好的内存。
模拟:
A* p = new A[10];
delete[] p;
#include <iostream>
using namespace std;
class A
{
public:
A(int a = 10)
:_a(a)
{
cout<<"A(int a = 10)"<<endl;
}
~A()
{
cout<<"~A()"<<endl;
}
private:
int _a;
};
int main()
{
A* p = (A *)operator new[](10*sizeof(A)+4);
int i = 0;
int count = 0;
*(int *)p = 10;
A *pStart = (A *)((int *)p+1);
for(i=0;i<10;i++)
{
new((A *)(int *)pStart + i) A(i);
}
count = *(int *)(pStart - 1);
for(i=0;i<count;i++)
{
pStart[i].~A();
}
operator delete[] ((A *)(int *)pStart-1);
return 0;
}