对于new来讲算法
计算所需内存的字节数,而后以此为参数调用标准库的operator new(size_t)函数数组
在operator new()返回的内存上调用类的适当的构造函数初始化一个对象函数
将operator new() 返回的指针做为表达式的运算结果spa
也即 new 把内存分配与对象构造合在一块儿了指针
对于delete来讲code
调用指针所指对象的析够函数释放对象自己对象
调用标准库的operator delete()函数将指针所指内存返还给系统继承
也即 delete 把释放对象自己与释放对象所占的内存合在一块儿内存
new[] 与 delete[] 行为与上相似编译器
不少时候并不须要当即在分配的内存上初始化一个对象,与此同时也但愿在释放内存以前不调用对象的析钩函数;allocator类提供了这种机制,其成员:
allocator<T> a; /* a能够用来分配原始内存以及在原始内存上构造T类型对象 */ a.allocate(n); /* 分配原始的内存,能够保存n个Type类型的对象 */ a.deallocate(p,n);/* 释放p所指的原始内存,p必须合法;而且不会调用p所指对象的析钩函数,n表示p所指的内存能够保存n个T类型对象 */ a.construct(p,t);/* 在p所指的内存上调用T类型的复制构造函数(以t为参数)初始化一个对象 */ a.destory(p);/* 调用p所指对象的析钩函数 */
若干个用于在原始内存上构造对象的算法:
uninitialized_copy(begin,end,begin2); /* 从迭代器[begin,end)指出的输入范围将元素复制到从迭代起begin2 * 开始的未构造的原始内存中,该函数是在目的地构造对象,而不是赋值 */ uninitialized_fill(begin,end,t) /* 将由迭代器[begin,end)指出的范围中的对象初始化为t的副本 * [begin,end)范围是未构造的原始内存,使用复制构造函数构造对象 */ uninitialized_fill_n(begin,end,t,n) /* 同上,不过至多构造n个对象 */
标准库提供了下列函数用于分配/释放原始的未构造的内存:
void* operator new(size_t) /* new表达式调用 */ void* operator new[](size_t) /* new[]表达式调用 */ void operator delete(void*) void operator delete[](void*)
用来在已经分配好的,原始的内存上调用构造函数初始化对象,与其余new表达式不一样,定位new表达式不会分配新的内存,其语法:
/* 在已经分配的原始内存上调用对象的默认构造函数构造对象 */ new(原始内存指针) Type /* 根据参数类型与参数个数调用合适的构造函数构造对象 */ new(原始内存指针) Type(初始化参数)
#include <stdio.h> #include <new> #include <malloc.h> class Test{ public: Test(){ printf("1\n"); } Test(int __a,int __b){ printf("2\n"); } ~Test(){ ; } }; int main(int argc,char *argv[]){ Test *ptr=(Test*)malloc(sizeof(Test)); new(ptr)Test; ptr->~Test(); new(ptr)Test(3,3); ptr->~Test(); free(ptr); return 0; }
不能重定义new与delete表达式的行为,可是能够自定义new与delete表达式的行为
当编译器看到类类型的new或delete表达式时,她查看该类是否有operator new 或operator delete成员
类定义(或继承)了本身的成员new和delete函数,则使用这些函数为对象分配/释放原始内存
不然,调用这些函数的标准库版本
#include <stdio.h> #include <new> #include <malloc.h> class Test{ public: void* operator new(size_t __size){ printf("1\n"); return ::operator new(__size); } }; int main(int argc,char *argv[]){ Test *test=new Test; delete test; return 0; }
自定义operator new与operator delete时只要注意参数类型,返回值类型便可
#include <stdio.h> #include <new> #include <malloc.h> class Test{ public: void operator delete(void* __p,size_t __size){ printf("Size: %zd\n",__size); /* __size无关紧要,若__size存在,编译器会把'delete p' * p所指对象所占内存字节传递给__size */ ::operator delete(__p); return ; } }; int main(int argc,char *argv[]){ Test *test=new Test; delete test; return 0; }
对于operator new:
#include <stdio.h> #include <new> #include <malloc.h> class A{ public: void* operator new(size_t __size){ printf("A\n"); return ::operator new(__size); } }; class B:public A{ public: void* operator new(size_t __size){ printf("B\n"); return ::operator new(__size); } }; int main(int argc,char *argv[]){ A *a=new A;/* 调用A的operator new */ A *b=new B;/* 调用B的operator new */ /* 分析new表达式的行为->与 B *b=new B 是同样的状况 */ delete a; delete b; return 0; }
对于 operator delete,B继承A,当B中未定义operator delete时:
#include <stdio.h> #include <new> #include <malloc.h> class A{ public: void operator delete(void *__p,size_t __size){ printf("Size: %zd\n",__size); ::operator delete(__p); } virtual ~A(){ ; } }; class B:public A{ int a; }; int main(int argc,char *argv[]){ A *a=new A; A *b=new B; delete a;/* a->A类型的对象,因此__size=sizeof(A) */ delete b; /* 因为A中存在虚析够函数,因此编译器会将b所指动态类型的 * 尺寸传递给__size,即__size=sizeof(B) */ return 0; }
当B中也定义了operator delete时:
#include <stdio.h> #include <new> #include <malloc.h> class A{ public: void operator delete(void *__p,size_t __size){ printf("A:Size: %zd\n",__size); ::operator delete(__p); } virtual ~A(){ ; } }; class B:public A{ int a; void operator delete(void *__p,size_t __size){ printf("B:Size: %zd\n",__size); ::operator delete(__p); } }; int main(int argc,char *argv[]){ A *a=new A; A *b=new B; delete a; /* 调用A::operator delete */ delete b; /* 调用的是B::operator delete */ return 0; }
在delete b 中调用的 B::operator delete 有一点疑惑不解,因为 operator new()与operator delete()在类中默认是静态成员函数(由于当 A *a=new A时,分配内存会先于对象构造,因此应该是静态函数) 因此她们 不可能同时又是虚函数,因此delete b应该调用的是A::operator delete;可是确确实实调用的是B::operator delete;想来大概是编译器的做用,记住就行
与上很是类似,如不在类继承层次中的自定义:
#include <stdio.h> #include <new> #include <malloc.h> class A{ public: A(){ printf("A\n"); } void* operator new[](size_t __size){ printf("A:new Size: %zd\n",__size); return ::operator new[](__size); } void operator delete[](void *__p,size_t __size){ printf("A:delete Size: %zd\n",__size); ::operator delete[](__p); return ; } virtual ~A(){ printf("~A\n"); } }; int main(int argc,char *argv[]){ A *a=new A[4]; delete[] a;/* 会把a所指内存的字节(即数组大小)传递给__size */ return 0; }
在类继承层次:
#include <stdio.h> #include <new> #include <malloc.h> class A{ public: A(){ printf("A\n"); } void* operator new[](size_t __size){ printf("A:new Size: %zd\n",__size); return ::operator new[](__size); } void operator delete[](void *__p,size_t __size){ printf("A:delete Size: %zd\n",__size); ::operator delete[](__p); return ; } void operator delete(void *__p,size_t __size){ printf("A:delete Size: %zd\n",__size); ::operator delete(__p); return ; } virtual ~A(){ printf("~A\n"); } }; class B:public A{ int b; public: B():b(0){ printf("B\n"); } void* operator new[](size_t __size){ printf("B:new Size: %zd\n",__size); return ::operator new[](__size); } void operator delete[](void *__p,size_t __size){ printf("B:delete Size: %zd\n",__size); ::operator delete[](__p); return ; } void operator delete(void *__p,size_t __size){ printf("B:delete Size: %zd\n",__size); ::operator delete(__p); return ; } virtual ~B(){ printf("~B\n"); } }; int main(int argc,char *argv[]){ A *b=new B; delete b;/* 正确释放 */ B *b2=new B[4]; delete[] b2;/* 能够正确释放 */ A *b1=new B[4]; delete[] b1;/* 此时提示段错误,编译器不能识别了... */ // delete[] (B*)b1 /* 便可 */ return 0; }
注意 delete[] b1 出错!