内存管理(一)
c++ 内存管理(一)
分配 | 释放 | 所属 | 可否重载 |
---|---|---|---|
malloc | free() | C函数 | 不可 |
new | delete | C++表达式 | 可 |
::operator new() | ::operator delete() | c++函数 | 可 |
allocator |
allocator |
c++标准库 | 自由搭配任何容器 |
new
A *a = new A();
上面代码我们申请了一个A类的对象使用new。
new里面的步骤
1.申请空间
2.调用A类的构造函数
3.返回指针
/**
new中大概是这样调用的
*/
A* a=NULL;
try{
void* mem = operator new(sizeof(A));//申请内存并返回指针
a = static_cast<A*>(mem);
a->A::A(); //调用构造函数,但是不允许这样做,只有编译器才能主动调用构造函数
}
catch(bad_alloc &memExp){
cerr<<memExp.what()<<endl;
}
operator new
那么operator new中又做了什么呢
/*
这是一个最简单的重写这个函数的方法,没有处理申请不到内存的情况。
*/
void* operator new(size_t sz)
{
return malloc(sz);
}
实际上operator new的伪代码
void* operator new(std::size_t size)throw(std::bad_alloc)
{
using namespace std;
if(size==0) //处理 0 byte申请
size=1; //视为 1 byte申请
while(true)
{
尝试分配size bytes
if(分配成功)
return 指针(一个指向分配的内存空间的指针)
//分配失败
new_hander globalHandler = set_new_handler(0)l
set_new_hander(globalHandler);
if(globalHandler)
(*globalHandler)();
else
throw std::bad_alloc();//抛出异常
}
}
可以看到operator new中不断尝试申请内存
new->::operator new->malloc()
//析构函数
~A()
{
printf("~A\n");
}
//重载operator delete
void operator delete(void *p)
{
printf("free\n");
free(p);
}
//main函数部分
...
a = new A();
a->~A();
operator delete(a);
...
stdout输出
~A
free
可以通过指针主动调用析构函数,再用operator delete释放内存
placement new
有时候我们需要在已经分配的内存上构造新的对象
class A
{
public:
int a;
void* operator new(size_t sz)
{
return malloc(sz);
}
void* operator new(size_t sz,void* p) //什么都不做直接把已经申请的空间返回
return p;
};
int main()
{
void *buf = NULL;
A *a = NULL;
try
{
buf = operator new(sizeof(A)); //申请buf空间
a = new(buf)A(); //在已申请的空间buf上创建对象
/*
这样相当于a = new(buf)A();这一句只执行的构造函数,绕过了a->A::a()这样直接调用构造函数,相当于我们直接调用了构造函数
*/
}
catch(bad_alloc &memExp)
{
cerr<<memExp.what()<<endl;
}
return 0;
}
搬砖啦