c++ 关于new文件

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;
}
原文地址:https://www.cnblogs.com/xiongqiangcs/p/3737545.html