包含new,new[],new(),::operator new(),...
::operator new() 本质就是调用malloc
::operator delete 本质就是调用free
举个有意思的例子
#ifdef __MSC_VER
int * p4 = allocator<int>().allocate(5, (int*)0);
allocator<int>().deallocate(p4, 5);
#endif
#ifdef __BORLANDC__
int * p4 = allocator<int>().allocate(5);
allocator<int>().deallocate(p4, 5);
//显然这是通过分配器来分配内存
#endif
#ifdef __GNUC__
void* p4 = alloc::allocate(512);
alloc::deallocate(p4, 512);
#endif
//在后续的版本只能够CNUC也更新到类似与BORLANDC
void *p5 = __gnu_cxx::__pool_alloc<int>().allocate(9);
__gnu_cxx::__pool_alloc<int>().deallocate((int*)p5, 9);
//__pool_alloc内存池水
接着举个使用new 的例子
或者说是new operator的过程
Complex *pc;
Complex * pc = new Complex(1, 2);
......
delete pc;
//下述就是Complex的new operator
try{
void * men = operator new(sizeof(Complex));
pc = static_cast<Complex*>(men);
pc->Complex::Complex(1, 2);
//能不能这样写不一定
}catch(std::bad_alloc){
}
void *operator new(size_t size, const std::nothrowt&) _THROW0*()
{
//std::nothrow设置为函数不抛出异常
void * p;
while((p = malloc(size)) == 0){
_TRY_BEGIN
if(_callnewh(size) == 0) break;
//callnewh调用这个函数,这玩意可以被自己设定
_CATCH(std::bad_alloc) return(0);
_CATCH_END
}
return (p);
}
//delete的使用过程
pc->~Complex();
operator delete(pc);
void __cdecl operator delete(void *p)_THROW0(){
free(p);
}
Complex* pca = new Complex[3];
delete[] pca;
malloc设计申请空间会给出一个cookie
内存结构可以看侯捷的课
placement new的使用方法大概如下
new(point)constructor();
使用array new与new的内存空间布局不一样
或指new(p)
或::operator new(size_t, void *)
形式如下
#include <new>
char * buf = new char[size(Complex) * 3];
Complex * pc = new(buf)Complex(1, 2);
delete [] buf;
//经过编译器的处理如下
try{
void * mem = operator new(sizeof(Complex), buf);
pc = static_cast<Complex*>(men);
pc -> Complex::Complex(1, 2);
}catch(std::bad_alloc){
}
member function 可重载
//假设存在一个Foo类
Foo::operator new(size_t);
Foo::operator delete(void *);
重载::operator new / :: operator delete
overloaded function
例子如下:
void myAlloc(size_t size){
return malloc(size);
}
void myFree(void * ptr){
return free(ptr);
}
inline void * operator new(size_t size){
return myAlloc(size);
}
inline void * delete delete(void * ptr){
return myFree(ptr);
}
class Foo{
public:
static void * operator new(size_t);
static void * operator delete(void *, size_t);
}
void * operator new(size_t size, void * start){
return start;
}//这个就是标准库已提供的placement new()的重载形式
void * operator new(size_t size, long extra){
return malloc(size + extra);
}//这个是崭新的placement new
void * operator new(size_t size, long extra, char init)
{
return malloc(size + extra);
}//这个也是一个崭新的placement new
一次malloc会多8个字节的cookie
内存池目标:
class Screen{
public:
static void * operator new(size_t);
static void operator delete(void*, size_t);
private:
Screen* next;
static Screen* freeStore;
static const int screenChunk;
private:
int i;
}
Screen* Screen::freeStore = null;
const int Screen::screenChunk = 24;
void * Screen::operator new(size_t size){
Screen *p;
if(!freeStore){
size_t chunk = screenChunk * size;
freeStrore = p = reinter_cast<Screen*>
(new char[chunk]);
for(; p != &freeStore[sceenChunk - 1]; ++ p){
p -> next = p + 1;
}
p -> next = null;
}
p = freeStore;
freeStore = freeStore -> next;
return p;
}
void Screen::operator delete(void *p, size_t){
(static_cast<Sreen*>(p))->next = freeStore;
freeStore = static_cast<Screen*>(p);
//头插法回收内存
//其实我在这里有个疑问
//我的问题是,如果空间不够用了呢
//好吧,其实我是傻逼,不够了,他会对应扩容
//然后回收的时候连接起来,这样的话,规模会越来越大
}
上述实现会多一个指针,有第二种实现
具体看侯捷课程,懒得抄
(xswl,借出来的内存不还233333)
当你受困必须为不容的classes重写一遍几乎想通的member operatornew 跟 operator delete,应该有对应的一个类来实现
就是下述的例子,都交给static allocator来实现
class Foo{
public:
long L;
string str;
static allocator myAlloc;
public:
Foo(long l):L(l){}
static void * operator new(size_t size){
return myAlloc.allocate(size);
}
static void operator delete(void * pdead, size_t size)
{
return myAlloc.deallocate(pdead, size);
}
}
allocate Foo::myAlloc;
偷懒真是一件神奇的事情,那么根据上述的例子,我们可以选择偷懒一波,所以引出了对应的macro for static allocator
例子如下
#define DECLARE_POOL_ALLOC() static void * operator new(size_t size){
return myAlloc.allocate(size);
}
static void operator delete(void * pdead, size_t size)
{ return myAlloc.deallocate(pdead, size);
}
#define IMPLEMENT_POOL_ALLOC(class_name)allocator class_name::myAlloc;
class Foo{
DECLARE_POOL_ALLOC()
};
IMPLEMENT_POOL_ALLOC(FOO)
//我猜等等应该要讲template
内容补充:
new handler
抛出exception之前会先调用一个可由client指定的handler
以下是new handler的形式与设定方法
typedef void(*new_handler)();
new_handler set_new_handler(new_handler p)throw();
new handler只有两个选择
void noMoreMemory(){
cerr << "out of memory";
abort();
}
set_new_handler(noMoreMemory);
海量小区块 会导致cookie的浪费
VC6标准allocator只是以::operator new 和 ::operator delete
完成allocate()和deallocate(),没有任何特殊的设计
BC5与VC6 allocator一样的实现效果
G2.9容器使用的分配器,不是std::allocator而是std::alloc
G4.9变化为__pool_alloc
G4.9有许多extended_allocators
原文:https://www.cnblogs.com/qq136155330/p/12490019.html