1)用来检测运用上的错误
使用new可能出现的问题:
- 若使用
new
,可能出现delete失败,而导致内存泄漏
;new
的内存,若出现多次delete将会导致未定义
行为;
而使用operator new:
- 可将会持有一串动态分配的地址,而
operator delete
将会容易检测出错误用法;
2)为了强化效能
operator new
不但可用于长时间执行的程序,也可用于少于1秒的程序
3)为了收集使用上的统计数据
可轻松收集分配区块的带下分布情况,
寿命分布
情况,倾向哪个次序分配和归还,运用型态是否随时间改变;
在许多情况下需要自定义(
全局性
/class专属
)来提高程序对内存操作的效率;
- 为了检测
运用错误
;- 为了收集动态分配内存值使用
统计信息
;- 为了
增加
分配和归还的速度
;
- 自定义将针对与
某特定类型
的对象设计的;- 为了
降低
缺省内存管理带来的空间额外开销
;
- 泛用型内存管理器内部会使用其他内存开销;
- 为了
弥补
缺省分配器中的非最佳齐位
;
- 泛用型内存管理器的动态分配采取的齐位并不确定;
- 为了将
相关对象成簇集中
;
- 将数据集中成簇在尽可能少的内存页中;
- 为了获得
非传统的行为
;
- 实现一些功能,而不使用传统的编译器定义的功能;
使用next指针;
#include
/***************************实现重载new***************************/
class MyTestOper
{
public:
/** 有参构造,将不会提供默认构造 */
MyTestOper(int x) : i(x){};
/** 获取i的接口 */
int get_i(){ return i; }
/** 重载new
==> 实现空间合理分配
*/
void* operator new(size_t);
/** 重载delete */
void operator delete(void *);
private:
MyTestOper *next;
static MyTestOper* freeP;
static const int chunkNum; // 内存块的大小
private:
int i;
};
MyTestOper* MyTestOper::freeP = 0;
const int MyTestOper::chunkNum = 24;
/** 重载new
==> 实现空间合理分配
*/
void *MyTestOper::operator new(size_t size)
{
MyTestOper *p = 0;
if (!freeP) // 判断内存是否为空
{
size_t chunk = size * chunkNum; // 块的大小
freeP = p = reinterpret_cast<MyTestOper*>(new char[chunk]);
/* 将内存切割 */
int x = 0;
for (; p != &freeP[chunkNum - 1]; ++p)
p->next = p + 1;
p->next = 0; // 此时p指向尾部
}
p = freeP; // 将p指向头部
freeP = freeP->next; // 而freeP指向下一个
return p;
}
/** 重载delete */
void MyTestOper::operator delete(void * delP)
{
(static_cast<MyTestOper *>(delP))->next = freeP;
freeP = static_cast<MyTestOper *>(delP);
}
/***************************不重载***************************/
class MyTestT
{
public:
/** 有参构造,将不会提供默认构造 */
MyTestT(int x) : i(x){};
/** 获取i的接口 */
int get_i(){ return i; }
private:
MyTestT *next;
static MyTestT* freeP;
static const int chunkNum; // 内存块的大小
private:
int i;
};
void main()
{
std::cout << "--------------重载的结果--------------" << std::endl;
std::cout << sizeof(MyTestOper) << std::endl;
size_t const N = 10;
MyTestOper *p[N];
for (int i = 0; i < N; ++i)
{
p[i] = new MyTestOper(i);
std::cout << p[i] << std::endl;
}
for (int i = 0; i < N; ++i)
{
delete p[i];
}
std::cout << "--------------不重载的结果--------------" << std::endl;
std::cout << sizeof(MyTestT) << std::endl;
MyTestT *pt[N];
for (int i = 0; i < N; ++i)
{
pt[i] = new MyTestT(i);
std::cout << pt[i] << std::endl;
}
for (int i = 0; i < N; ++i)
{
delete pt[i];
}
system("pause");
}
借用union,将一个对象前4个字节当作指针(
next
)来使用,通过该指针能够将其他的内存进行衔接;一旦该内存被分配出去则前4个字节的next将不要被需要;
#include
using namespace std;
class Airplane {
private:
struct AirplaneRep{
unsigned long miles;
char type;
};
union {
AirplaneRep rep;
Airplane* next;
};
public:
unsigned long getMiles() { return rep.miles; }
char getType() { return rep.type; }
void set(unsigned long m, char t) {
rep.miles = m;
rep.type = t;
}
public:
static void* operator new(size_t size);
static void operator delete(void* deadObject, size_t size);
private:
static const int BLOCK_SIZE; // 块大小
static Airplane* headOfFreeList; // 链表
};
Airplane* Airplane::headOfFreeList;
const int Airplane::BLOCK_SIZE = 512;
/* 申请内存块 */
void* Airplane::operator new(size_t size){
if (size != sizeof(Airplane))
return ::operator new(size);
Airplane* p = headOfFreeList;
if (p)
headOfFreeList = p->next;
else{
/* 申请一大块内存 */
Airplane* newBlock = static_cast<Airplane*>(
::operator new(BLOCK_SIZE * sizeof(Airplane))
);
/* 切割内存块 */
for (int i = 1; i < BLOCK_SIZE - 1; ++i) {
newBlock[i].next = &newBlock[i + 1];
}
newBlock[BLOCK_SIZE - 1].next = 0;
p = newBlock;
// 指向头部
headOfFreeList = &newBlock[1];
}
return p;
}
/* 回收一个内存块,将它放到链表前端 */
void Airplane::operator delete(void* deadObject, size_t size) {
if (deadObject == 0) return;
if (size != sizeof(Airplane)){
::operator delete(deadObject);
return;
}
Airplane* carcass = static_cast<Airplane*>(deadObject);
carcass->next = headOfFreeList;
headOfFreeList = carcass;
}
/***************************不重载***************************/
class MyTestT
{
public:
/** 有参构造,将不会提供默认构造 */
MyTestT(){};
private:
struct AirplaneRep{
unsigned long miles;
char type;
};
union {
AirplaneRep rep;
Airplane* next;
};
};
int main()
{
size_t const N = 10;
std::cout << "--------------重载的结果--------------" << std::endl;
std::cout << sizeof(Airplane) << std::endl;
Airplane *p[N];
for (int i = 0; i < N; ++i)
{
p[i] = new Airplane;
std::cout << p[i] << std::endl;
}
for (int i = 0; i < N; ++i)
{
delete p[i];
}
std::cout << "--------------不重载的结果--------------" << std::endl;
std::cout << sizeof(MyTestT) << std::endl;
MyTestT *pt[N];
for (int i = 0; i < N; ++i)
{
pt[i] = new MyTestT;
std::cout << pt[i] << std::endl;
}
for (int i = 0; i < N; ++i)
{
delete pt[i];
}
system("pause");
return 0;
}
将该内存管理进行提取到一个类中,即不需要在每个类中进行重写,直接引入该类即可使用;
#include
using namespace std;
class Allocator{
private:
struct obj {
struct obj* next;
};
public:
void* allocate(size_t);
void deallocate(void*, size_t);
private:
obj* freeStore = nullptr;
const int CHUNK = 5;
};
/** 分配 */
void* Allocator::allocate(size_t size){
obj* p;
if (!freeStore){
size_t chunk = CHUNK * size;
freeStore = p = (obj*)malloc(chunk);
for (int i = 0; i < CHUNK - 1; ++i) {
p->next = (obj*)((char*)p + size);
p = p->next;
}
p->next = nullptr;
}
p = freeStore;
freeStore = freeStore->next;
return p;
}
/** 回收 */
void Allocator::deallocate(void* p, size_t size) {
((obj*)p)->next = freeStore;
freeStore = (obj*)p;
}
/****************************************测试****************************************/
class Airplane {
private:
int m_a;
static Allocator myAlloc;
public:
Airplane(int i) : m_a(i){}
static void* operator new(size_t size){
return myAlloc.allocate(size);
}
static void operator delete(void* p, size_t size){
return myAlloc.deallocate(p, size);
}
};
Allocator Airplane::myAlloc;
int main()
{
size_t const N = 10;
std::cout << "--------------重载的结果--------------" << std::endl;
std::cout << sizeof(Airplane) << std::endl;
Airplane *p[N];
for (int i = 0; i < N; ++i)
{
p[i] = new Airplane(i);
std::cout << p[i] << std::endl;
}
for (int i = 0; i < N; ++i)
{
delete p[i];
}
system("pause");
return 0;
}
将该类进一步简化使用,将其定义为宏;
#include
using namespace std;
class Allocator{
private:
struct obj {
struct obj* next;
};
public:
void* allocate(size_t);
void deallocate(void*, size_t);
private:
obj* freeStore = nullptr;
const int CHUNK = 5;
};
/** 分配 */
void* Allocator::allocate(size_t size){
obj* p;
if (!freeStore){
size_t chunk = CHUNK * size;
freeStore = p = (obj*)malloc(chunk);
for (int i = 0; i < CHUNK - 1; ++i) {
p->next = (obj*)((char*)p + size);
p = p->next;
}
p->next = nullptr;
}
p = freeStore;
freeStore = freeStore->next;
return p;
}
/** 回收 */
void Allocator::deallocate(void* p, size_t size) {
((obj*)p)->next = freeStore;
freeStore = (obj*)p;
}
/****************************************定义宏****************************************/
#define DECLARE_POOL_ALLOC()\
public:\
void* operator new(size_t size){ return myAlloc.allocate(size); }\
void operator delete(void* p, size_t size) { return myAlloc.deallocate(p, size); }\
protected:\
static Allocator myAlloc;
#define IMPLEMENT_POOL_ALLOC(class_name)\
Allocator class_name::myAlloc;
/****************************************测试****************************************/
class Airplane {
private:
int m_a;
DECLARE_POOL_ALLOC();
public:
Airplane(int i) : m_a(i){}
};
IMPLEMENT_POOL_ALLOC(Airplane);
int main()
{
size_t const N = 10;
std::cout << "--------------重载的结果--------------" << std::endl;
std::cout << sizeof(Airplane) << std::endl;
Airplane *p[N];
for (int i = 0; i < N; ++i)
{
p[i] = new Airplane(i);
std::cout << p[i] << std::endl;
}
for (int i = 0; i < N; ++i)
{
delete p[i];
}
system("pause");
return 0;
}
当内存使用不足,无法申请内存时会抛出一个
std::bad_alloc exception
的异常。但编译器设置,在抛出异常前,可指定调用new_handle
。
- 故我们可以使用
new_handle
对使用的内存进行检查,并即使清理被暂用且没有使用的内存从而让这次的申请成功;- 通过
set_new_handle
传入;
new_handle中一般实现这个两种处理方式:
释放部分内存
,让内存被申请成功;- 调用
abort()
或exit()
;
void new_handle()
{
…………
}
new_handle set_new_handle(new handle p) throw();