关闭

编写高质量代码:改善C++程序的150个建议(连载15)

发表于:2012-4-23 10:09

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:李健    来源:51Testing软件测试网采编

  建议29:区分new的三种形态

  C++语言一直被认为是复杂编程语言中的杰出代表之一,不仅仅是因为其繁缛的语法规则,还因为其晦涩的术语。下面要讲的就是你的老熟人—new:

  它是一个内存管理的操作符,能够从堆中划分一块区域,自动调用构造函数,动态地创建某种特定类型的数据,最后返回该区域的指针。该数据使用完后,应调用delete运算符,释放动态申请的这块内存。

  如果这就是你对new的所有认识,那么我不得不说,你依旧被new的和善外表所蒙蔽着。看似简单的new其实有着三种不同的外衣。

  是的,你没有看错,也不用感到惊奇,一个简单的new确实有三种不同的形态,它扮演着三种不同的角色,如下所示:

  1. new operator  
  2. operator new  
  3. placement new

  下面的代码片段展示的是我们印象中熟悉的那个new:

  1. string *pStr = new string("Memory Management");  
  2. int *pInt = new int(2011);

  这里所使用的new是它的第一种形态new operator。它与sizeof有几分类似,它是语言内建的,不能重载,也不能改变其行为,无论何时何地它所做的有且只有以下三件事,如图3-2所示。

图3-2 new operator所完成的三件事

  所以当写出“string *pStr = new string("Memory Management");”代码时,它其实做的就是以下几件事:

  1. //为string对象分配raw内存  
  2. void *memory = operator new( sizeof(string) );  
  3. //调用构造函数,初始化内存中的对象  
  4. call string::string()on memory;  
  5. //获得对象指针  
  6. string *pStr = static_cast<string*>(memory);  
  7. 当然,对于内置类型,第二步是被忽略的,即:  
  8. //为int分配raw内存  
  9. void *memory = operator new( sizeof(int) );  
  10. //获得对象指针  
  11. int *pInt = static_cast<int*>(memory);

  其实new operator背后还藏着一个秘密,即它在执行过程中,与其余的两种形态都发生了密切的关系:第一步的内存申请是通过operator new完成的;而在第二步中,关于调用什么构造函数,则由new的另外一种形态placement new来决定的。

  对于new的第二种形态—内存申请中所调用的operator new,它只是一个长着“明星脸”的普通运算符,具有和加减乘除操作符一样的地位,因此它也是可以重载的。

  operator new在默认情况下首先会调用分配内存的代码,尝试从堆上得到一段空间,同时它对事情的结果做了最充分的准备:如果成功则直接返回;否则,就转而去调用一个new_hander,然后继续重复前面过程,直到异常抛出为止。所以如果operator new要返回,必须满足以下条件之一:

  内存成功分配。

  抛出bad_alloc异常。

41/41234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号