new文件用来管理c++的动态内存,这个文件声明了几个全局空间的函数(不是std空间的函数,全局空间的函数调用时是用全局作用域解析符),包括operator
new 和operator delete的重载 ,这些函数用于处理动态存储空间请求。
其new的头文件源代码
#ifndef _NEW
#define _NEW#include <cstddef>
#include <exception>extern "C++" {
namespace std
{//注意此空间内函数或者变量处于std空间,使用时需要添加std::调用
/**
* 当内存分配错误的时候抛出bad_alloc异常
*/
class bad_alloc : public exception
{
public:
bad_alloc() throw() { }
virtual ~bad_alloc() throw();
};//当内存分配失败时用此结构体替代异常,使用嵌入式环境,嵌入式环境没有异常功能
struct nothrow_t { };
extern const nothrow_t nothrow;///当内存分配失败时,调用new_handler
///new_handler试着去分配更多得存储空间,当且仅当申请内存成功时,才会返
///否则抛出bad_alloc异常或者终止程序(调用abort或者exit)
typedef void (*new_handler)();
new_handler set_new_handler(new_handler) throw();
} // namespace std//全局空间函数,调用时加上作用域解析符,如::operator new ()
void* operator new(std::size_t) throw (std::bad_alloc);
void* operator new[](std::size_t) throw (std::bad_alloc);
void operator delete(void*) throw();
void operator delete[](void*) throw();
void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();
void operator delete(void*, const std::nothrow_t&) throw();
void operator delete[](void*, const std::nothrow_t&) throw();//placement operator new/delete
inline void* operator new(std::size_t, void* __p) throw() { return __p; }
inline void* operator new[](std::size_t, void* __p) throw() { return __p; }inline void operator delete (void*, void*) throw() { }
inline void operator delete[](void*, void*) throw() { }} // extern "C++"
#endif
1、关于new operator与operator new
operator new() 仅仅分配内存空间,是对malloc的一个封装,返回的是一个void
*,如
int* a = (int *)::operator new(sizeof(int));
只是对a分配了空间,通过vs2012进行调试你会发现operator new
的实现如下:其主要是调用malloc(size),而没有对内存进行初始化
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) { // try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{ // report no memory
static const std::bad_alloc nomem;
_RAISE(nomem);
}return (p);
}
对于new operator先调用operator new分配内存空间,然后调用构造函数初始化
#include <iostream>
using namespace std;class Foo{
public:
Foo(){
cout<<"Foo constructor"<<endl;
a = 10;
}//对operator new进行重写
void* operator new(size_t size){
cout<<"Foo operator new"<<endl;
return ::operator new(size);
}int a;
};int main(){
Foo* f1 =(Foo *) ::operator new(sizeof(Foo));
cout<<f1->a<<endl;
Foo* f2 = new Foo();
cout<<f2->a<<endl;
}/***************
结果为:
3420040
Foo operator new
Foo constructor
10*****************/
由于operator new 只是分配空间未调用构造函数,所以公有变量未初始化,是个随机值,
而new Foo() 先调用operator new 然后再构造函数,所以会先出现Foo operator new
2、关于placement new(定位放置new)
placement new 是operator
new的一个重载的版本,如果你想在已经分配的内存中创建一个对象,这时不能使用new。而placement
new永许你在一个已经分配好的内存中(栈或者堆中)构造一个新的对象,原型中void*
p实际就是指向一个已经分配好的内存缓冲区的首地址。c++支持placement operator
new,能够在预先分配的缓冲区中构造对象,避免new内存分配时查找内存和分配内存的时间,而且由于内存已经分配,没有内存分配失败的危险,在内存池,垃圾回收器,和性能或异常安全可以使用
char *buf = new char[sizeof(string)]; // pre-allocated buffer
string *p = new (buf) string("hi"); // placement new
char memory[sizeof(Foo)];
void* place = memory;Foo* f = new(place) Foo();
3、关于set_new_handler
new_handler类型的函数是默认内存申请函数(operator new和operator new[])申请内存失败,会被调用。
new_handler函数会试图为新的内存申请请求提供更多的可用空间。当且仅当,函数成功地提供了更多的可用空间,它才返回。
否则,要么抛出bad_alloc异常(或bad_alloc派生类)要么终止程序(比如调用abort或exit)。
如果new_handler函数返回(即,它提供了更多可用空间)后,当内存申请函数申请指定的内存空间失败时,它会被再次调用,或直到new_handle函数不返回或被替换。
#include <iostream>
#include <new>char* memoryPool = NULL;
void my_new_handler(){
if(NULL != memoryPool){
// 删除一些不用的内存
delete[] memoryPool;
memoryPool = NULL;
}else{
//没有足够的内存
throw std::bad_alloc();
}
return ;
}int main(){
std::set_new_handler(my_new_handler);
memoryPool = new char[512*1024*1024];
if(memoryPool == NULL){
std::cout<<"allocator fail"<<std::endl;
return -1;
}
char *p = NULL;
for(int i = 0 ; i < 4; ++ i){
p = new char[256*1024*1024];
std::cout<<i+1<<" allocator 512M "<<p<<std::endl;
}
return 0;
}
c++ 关于new文件