如果正在删除的对象指针是0,将不发生任何事情
内存管理的开销
1.调用malloc(),从堆里申请一块内存
2.从堆里搜索出一块足够满足请求的内存。可以挺过检查显示内存使用情况的某种图或目录来实现搜索。这个过程很快,但可能要试探几次。
3.在指向这块内存的指针返回之前,这块内存大小和地址必须记录下来,这样以后调用malloc()时就不会再使用它了,而且当调用free()时,系统就会知道要释放多大的内存。
用完内存
当运算符new找不到足够大的连续内存块来安排对象时将会发生什么?一个称为new-handle的函数被调用,或者检查指向函数的指针,如果指针非零,那么它指向的函数被调用。
对于new-handler的缺省动作是抛出一个异常。然而,如果在程序里用堆分配,至少要用“内存已用完”的信息代替new-handler,并异常中断程序。
通过包含new.h,然后以想装入的函数地址作为参数调用set_new_handler()函数,这样就替换了new-handler
#include <iostream> #include <stdlib.h> #include <new.h> using namespace::std; void out_of_memory() { cerr << "memory exhausted!" << endl; exit(1); } int main() { set_new_handler(out_of_memory); while(1) new int[1000]; //Exhausted memory } 重载new和delete 当重载运算符new和delete时,记住只改变原有的内存分配方法是很重要的。编译器将用new代替缺省的版本去分配内存,然后为那个内存调用构造函数。所以,虽然编译器遇到new时会分配内存并调用构造函数,但当我们重载new时,可以改变的只是内存分配部分。 当重载运算符new时,也可以替换它用完内存时的行为,所以必须在运算符new里决定做什么:返回0、写一个调用new-handler的循环、再试着分配或用一个bad_alloc异常处理 重载全局new和delete 当全局版本的 new和delete不能满足整个系统时,对其重载是很极端的方法。如果重载全局版本,那么缺省版本就完全不能被访问--甚至在这个重载定义里也不能调用他们。 重载的new必须有一个size_t参数,返回值是一个void*。 运算符delete接受一个指向由new分配的内存的void*,返回值是void。 #include <stdio.h> #include <stdlib.h> void* operator new(size_t sz) { void* m = malloc(sz); return m; } void operator delete(void* m) { free(m); } 为一个类重载new和delete 为一个类创建new和delete时,不必说明是static,我们仍然是在创建static成员函数。当编译器看到使用new创建类对象时,它选择成员版运算符new而不是全局版的new。但全局版的new和delete为所有其他类型对象使用。(除非他们有自己的new和delete)。 对象纺织 重载运算符new还有其他两个不常见用途: 1.可能想要在内存 的指定位置上放置一个对象 2.可能想在调用new时,可以从不同的内存分配器中选择 这两种情形都用相同的机制解决:重载运算符new可以带多于一个的参数 #include <stddef.h> #include <iostream> using namespace::std; class X { int i; public: X(int I = 0) : i(I) {} ~X() { cout << "X::~X()" << endl; } void* operator new(size_t, void* loc) { return loc; } }; int main() { int l[10]; X* xp = new(l) X(47); xp->X::~X(); }