new/delete是c++中动态构造对象的表达式 ,一般情况下的new/delete都是指的new/delete表达式,这是一个操作符,和sizeof一样,不能改变其意义。

new/delete表达式的声明如下:

::(optional) new (placement_params)(optional) ( type )initializer(optional)
::(optional) delete expression  

除了全局作用符::和初始化参数,还有个 placement_params,这是不常见的,要理解这个参数的作用,就要了解operator new和placement new。

众所周知,new表达式做了两个工作:1.分配内存;2.在分配的内存上调用构造函数构造对象。比如我们分配一个string对象

string *str = new string(“Kian”);

编译器首先调用operator new分配一块内存,类似于malloc,然后在mem上面调用构造函数,

1.void *mem = operator new(sizeof(string));

2. create string at men.

第二步我们是控制不了的,但是operator new却是可以修改的。

Operator new/delete的声明如下:

void* operator new  ( std::size_t count );
void* operator new ( std::size_t count, const std::nothrow_t& tag);
void operator delete ( void* ptr );
void operator delete ( void* ptr, const std::nothrow_t& tag);

第二种带参数tag的声明称为nothrow形式,因为现在的operator new如果分配内存失败的话会抛出bad_alloc异常. 有时候我们不想抛出异常,而是根据返回值判断内存分配失败与否,nothrow形式就是这个作用,失败时不抛出异常,而是返回null指针。

我们可以直接重载operator new, 定制自己的内存分配策略,常见的作用是优化内存使用性能。重载operator new不需要看见声明就可以直接使用。我们重定义一个简单的版本:

void* operator new(std::size_t size){
printf("operator new called, size=%d\n", size);
return malloc(size);
} void operator delete(void *ptr){
printf("operator delete called\n");
free(ptr);
} int main(){
int *i = new int();
delete i;
std::string *str = new std::string("Kian");
delete str;
}

运行结果:

operator new called, size=4

operator delete called

operator new called, size=4

operator new called, size=17

operator delete called

operator delete called

可是有时候我们希望拥有更多的功能,比如记录内存分配释放的位置,用于检测内存错误,或者直接在已有的内存上构造对象,那么必须定义更多参数,这就需要placement new/delete,声明如下.

void* operator new  ( std::size_t count, void* ptr );
void* operator new ( std::size_t count, user-defined-args... );
void operator delete ( void* ptr, void* place);
void operator delete ( void* ptr, user-defined-args...); 

可以直接在已有内存上构造对象:

void *mem = (void*)malloc(sizeof(int));
int *j = new(mem) int();
printf("mem=%p, j=%p, *j = %d\n",mem, j, *j);
free(mem);

运行结果:

mem=0x8a48008, j=0x8a48008, *j = 3

可以看出new直接在mem上面构造了对象。

目前,void* operator new  ( std::size_t count, void* ptr )在全局域还不能被重载,但是void* operator new  ( std::size_t count, user-defined-args... )可以自由定义。

比如记录内存分配发生的位置:

void* operator new(std::size_t size){
printf("operator new called, size=%d\n", size);
return malloc(size);
} void operator delete(void *ptr){
printf("operator delete called\n");
free(ptr);
} void* operator new(std::size_t size, char* filename, int line){
printf("new called at %s:%d size=%d \n", filename, line, size);
return ::operator new(size);
} void operator delete(void *place, char* filename, int line) {
printf("delete called at %s:%d place=%p \n", filename, line, place);
::operator delete(place);
} int main(){
int *k = new(__FILE__, __LINE__) int();
printf("k=%p *k=%d \n", k, *k);
delete k;
}

运行结果:

new called at testnew.cpp:41  size=4

operator new called, size=4

k=0x847f008 *k=1

operator delete called

在每个new中打印了文件名和行号,不过细心的你会发现delete时并没有调用重载的placement delete ,这个delete只有在构造对象时抛出了异常才会调用,我们写一个简单的class来看看:

class ThrowExcept {
public:
ThrowExcept(int v):value_(v){ throw ;}
private:
int value_;
}; int main(){
ThrowExcept *t;
try{
t = new(__FILE__, __LINE__) ThrowExcept();
}catch(int &e){
printf("catch exception %d\n", e);
}
}

运行结果:

new called at testnew.cpp:53  size=4

operator new called, size=4

delete called at testnew.cpp:53  place=0x9e2e008

operator delete called

catch exception 1

自定义的delete被正常调用,这么做的原因在于如果构造函数抛出异常,系统正常的operator delete并不知道用户自定义的placement new做了什么,自然也不知道怎么去释放。所以如果自己定义placement new, 一定要定义对应的palcement delete,不然可能出现memory leak。

http://en.cppreference.com/w/cpp/memory/new/operator_new

http://en.cppreference.com/w/cpp/language/new

《effective/more effective c++》

new表达式,operator new和placement new介绍的更多相关文章

  1. new 、operator new 和 placement new

    一.原生operator new 我们先从原生operator new开始.考虑如下代码,它用来分配5个int型的空间并返回指向他们的指针[1]: int* v = static_cast<in ...

  2. C++ 中 new 操作符内幕:new operator、operator new、placement new

    一.new 操作符(new operator) 人们有时好像喜欢有益使C++语言的术语难以理解.比方说new操作符(new operator)和operator new的差别. 当你写这种代码: st ...

  3. C++中的new,operator new与placement new

    以下是C++中的new,operator new与placement new进行了详细的说明介绍,需要的朋友可以过来参考下     new operator/delete operator就是new和 ...

  4. 浅谈new operator、operator new和placement new 分类: C/C++ 2015-05-05 00:19 41人阅读 评论(0) 收藏

    浅谈new operator.operator new和placement new C++中使用new来产生一个存在于heap(堆)上对象时,实际上是调用了operator new函数和placeme ...

  5. 浅析C++内存分配与释放操作过程——三种方式可以分配内存new operator, operator new,placement new

    引言:C++中总共有三种方式可以分配内存,new operator, operator new,placement new. 一,new operator 这就是我们最常使用的 new 操作符.查看汇 ...

  6. 小结:c++中的new、operator new和placement new

    小结:c++中的new.operator new和placement new new(也称作new operator),是new 操作符,不可重载 class T{...}; T *t = new T ...

  7. C++中的new、operator new与placement new

    转:http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html new/delete与operator new/operator ...

  8. new、operator new、placement new

    首先我们区分下几个容易混淆的关键词: new.operator new.placement new new和delete操作符我们应该都用过,它们是对堆中的内存进行申请和释放,而这两个都是不能被重载的 ...

  9. C++ new operator, delete operator, operator new, operator delete, new placement

    http://www.younfor.com/cpp-new-placement-new-operator-new.html http://www.cnblogs.com/luxiaoxun/arch ...

随机推荐

  1. 401. Binary Watch 回溯

    A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom ...

  2. Redis简单集群配置

    参考链接为:http://blog.csdn.net/u014230881/article/details/71123494 比较系统学习和熟练使用Redis命令可参考该教程:http://www.r ...

  3. [转]开源实时视频码流分析软件:VideoEye

    原文太长了,就直接贴上链接,以便大家学习. 引文链接:开源实时视频码流分析软件:VideoEye

  4. Ubuntu16.04配置单机版Zookeeper和Kafka

    1. 配置zookeeper单机模式 选择的是zookeeper-3.4.10版本,官网下载链接:http://mirrors.hust.edu.cn/apache/zookeeper/stable/ ...

  5. FD.io社区中国行暨未来网络技术沙龙·南京站 会议小结

    What is FD.io VPP? FD.io VPP(Fast Data Input/Output Vector Packet Processing)is a new network multi- ...

  6. 关于Oracle的认识

    一.Oracle认识: 1.安装时的全局数据库Orcl可以使用吗?可以的 2.Oracle相关服务: 3.数据库与用户,表空间的关系“ 4.切换数据库 5.关于命令:sqlplus 6\

  7. Unity-iPhone has Conflicting Provisioning Settings

    Select the top level node called Unity-iPhone in the left tree view (the one with the blue item). Se ...

  8. MySQL学习【第八篇索引优化】

    一.建立索引的原则(规范) 1.选择唯一性索引 只要可以创建唯一性索引的,一律创建唯一索引(因为速度快呀) 判断是否能创建唯一索引,用count(列名),count(distinct(列名))一样就能 ...

  9. solve the promble of VMware Workstation Ubuntu18.04 ethernet interface losting

    $ ifconfig -aens33: flags=4098<BROADCAST,MULTICAST>  mtu 1500    ether 00:**:**:**:**:**  txqu ...

  10. 什么是设计模式?【php】

    原文地址:https://www.cnblogs.com/zhuiluoyu/p/5818974.html 什么是设计模式? 设计模式(Design Pattern)是一套被反复使用.多数人知晓的.经 ...