new,operator new,placement new
来源:互联网 发布:js中的element 编辑:程序博客网 时间:2024/05/16 13:49
int *p = (int *) operator new(sizeof(int));new(p) int(1) ;先用普通的operator new分配需要的内存,然后用new(void *)表达式实现对象的构造。
(五)重载operator new的时机
为什么要重载operator new呢?重载operator new能有什么好处?
总结起来有几点:
(1)特殊情形下的定制版效能更高:
编译器所带的operator new和operator delete需要适合大多数的场景,包括处理大块内存,小块内存,大小混合型内存等,这会带来内存破碎问题,性能在某些场景下偏低的问题等。通过对某些应用场景进行定制,则有可能达到用更快的速度,更少的内存完成内存分配。例如下面的场景:
需要分配大量的小块内存,例如我们要定义大量的class AA对象,那么我们可以定义AA的operator new成员函数,专门来管理类AA的内存。
(2)收集使用上的数据
通过定制new和delete,我们可以统计内存块的分配状态:每次分配的大小,寿命,分配的最大动态内存等使用情况
(3)检测运用上的错误
最常用的一个场景是在定制的operator new中分配超额的内存,以额外空间放置特定的字节作为签名,当执行operator delete时检查签名是否被改。通过这个签名是否被改能够判断出是否有越界的行为。
六.一个合格的operator new函数应该是怎么样的
每一个operator new有其要固守的一些常规,例如:
(1)返回的地址必须符合内存对齐规则
(2)错误处理:如果内存分配成功则直接返回申请的内存地址,如果失败,最终会返回一个NULL或抛出一个异常。在返回或抛异常之前,会有一个循环:一直调用new-handling函数直到内存分配成功,或者new-handling被设置为空则跳出循环:
C++标准库的new-hanlding函数在operator new函数分配内存失败时被调用;用户可以定制自己的new-hanlding函数,通过标准库的set_new_handler()函数来替换标准库的new-handling函数。
参考一下vs2010中operaotr new的实现可以更清晰的看到这两点固守的常规:
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); }
值得注意的是,内存分配是通过调用malloc()实现的,而malloc()分配的内存保证是内存对齐的;另外,可以很明显的看到确实包含了一个while循环。
七.重载operator new的方式和其对主程序和第三方库的影响
重载operator new的方式有几种,按作用域分:
(1)重载全局operator new
(2)重载的operator new作为类成员函数(隐式静态)
按函数调用形式分:
(1)正常的operator new形式,只有一个size_t类型参数
(2)placement new形式,可以有一个附加的参数
其中,全局的正常形式operator new是侵略性最大的,因为使用方无需看到该重载函数的声明,即使用方无需包含重载operator new的文件;
如果我们的程序与第三方库进行交互,那么必须注意全局operator new的这种侵略性。最重要的原则是,在哪个库申请的内存必须在这个库里面归还内存,因为一旦重载了全局operator new,就不能保证不同的库之间使用的是同个分配器。如果确实需要跨库申请和归还内存,那么库必须提供对应的接口来注册申请内存和归还内存的函数。
另外,考虑一下,库一般以二进制形式和头文件形式提供给用户使用,如果以二进制形式提供,那么不会受到我们重载的全局operator new影响,但是如果是以头文件形式提供的,那么在这些头文件中调用到的new就会在无形中使用了我们重载的operator new,最典型的就是那些模板库了。例如标准库的容器类。看看下面的一个例子:
void *operator new(size_t size){std::cout << "our opertaor new!" << std::endl ;return malloc(size) ;}int _tmain(int argc, _TCHAR* argv[]){std::vector<int > v1 ;v1.push_back(1) ; //容器获取新的内存若是使用了我们重载的operator new,则能看到“our operator new”的输出。system("pause") ; return 0;}输出结果:
our operaotr new!
所以,std::vector在分配内存时,调用的是我们重载的operaotr new函数
若在全局区域重载的是placement new,则需要使用方看到该placement new的声明,例如:
在A文件中:void *operator new(size_t , bool flag) ;
在B文件中必须有同样的该operator new的声明,或者直接包含A文件,才能使用下面的new表达式形式:
int *p = new(true) int ;
- placement new operator new
- new; operator new; placement new
- new, operator new, placement new
- new、operator new、placement new
- new、operator new、placement new
- new,operator new,placement new
- placement new, operator new and new operator
- placement new, operator new and new operator
- placement new, operator new and new operator
- 关于new operator, operator new, placement new
- placement new, operator new and new operator
- operator new,new operator, placement new
- Placement new、operator new、new operator
- new operator /operator new 和placement new
- new operator,operator new,placement new
- Placement new、operator new、new operator
- C++ operator new placement new
- new 、operator new 和 placement new 区别
- 详解Java中的泛型
- 数字图像基本操作及灰度调整
- 标准模板库 STL-2 编程题#6: priority queue(Coursera 程序设计与算法 专项课程3;容器中自定义排序顺序 MyCompare,判断质数)
- hdu 1532 Drainage Ditches 和hdu 3549 Flow Problem 网络流入门(EK和dinic)
- From Java To Kotlin
- new,operator new,placement new
- Spring Mvc controller单元测试
- 文章标题
- SQL Server with as使用
- 源码编译同时生成odex和apk文件的坑
- 有道词典
- Unity小技巧-清除缓存
- Spring4和Hibernate4整合后事务不起作用
- 7.7用穷举法求最大约数(1)