Note of Justin

关于工作和读书的笔记

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  47 Posts :: 0 Stories :: 45 Comments :: 0 Trackbacks

留言簿(14)

搜索

  •  

积分与排名

  • 积分 - 50691
  • 排名 - 434

最新评论

阅读排行榜

评论排行榜

[原创文章欢迎转载,但请保留作者信息]
Justin 于 2010-06-15


在item16和17里大师曾经介绍过,一个new的过程大致分两步:
   - 申请内存
   - 调用构造函数构造新对象

如果第一步成功而第二步失败,一个成熟的系统应该能回撤第一步,释放刚分配的内存空间。
如果第一步用的是普通的new函数,C++是能够找到与之匹配的delete函数的。
//normal form of new operator
void* operator new(std::size_t) throw(std::bad_alloc);
//is matched with the global one
void operator delete(void *rawMemory) throw();
//or the class-scope one
void operator delete(void* rawMemory, std::size_t size) throw();

而如果用的是非常规的new函数,情况就不一样了。这里说的“非常规new”,指的是placement new。
这里说的placement new指的是除去size_t参数外,还包含了其他的参数的new函数。
   最原始的placement new版本在C++的new库中:
void* operator new(std::size_t, void *pMemory) throw();

   比较常见的用途是申请一大批内存放在某个vector中,到需要分配内存的时候用该placement new指定在某个地址开始申请内存。

在调用placement new的过程中,一旦第二步出错,系统依照惯例会用一个delete来释放内存,不过因为这次new的方式不同寻常,也就需要一个不同寻常的delete来释放。
系统需要的是一个参数类型、个数都一致的delete,placement delete来释放由那个placement new鼓捣出来的内存空间。
如果找不到……对不起,内存泄漏。

但是有一点需要注意的是:如果使用了placement new,除了要写好与之对应的placement delete外,还要再写一个“常规”的delete函数。
因为对于delete而言,placement delete是在当placement new遇见失败异常时释放新近分配的内存用的;“常规”的delete则是用于正常途径的delete。如下的语句,是不会调用placement delete的。
delete aObject;

最后要提的一点是:注意不同名字域中的名字覆盖/隐藏。
如果在某个类中只声明了一个placement new,那么用户就无法使用全局范围的默认new函数;如果子类中只声明了一个placement new,那么父类的另外形式的new函数就会被隐藏。如何做到透明的使用所有可能的new/delete?
直接粘贴大师的代码吧,一来是这个已经很直接没有必要再另做消化,二来我感冒了……

class StandardNewDeleteForms {
public:
  
// normal new/delete
  static void* operator new(std::size_t size) throw(std::bad_alloc)
  { 
return ::operator new(size); }
  
static void operator delete(void *pMemory) throw()
  { ::
operator delete(pMemory); }

  
// placement new/delete
  static void* operator new(std::size_t size, void *ptr) throw()
  { 
return ::operator new(size, ptr); }
  
static void operator delete(void *pMemory, void *ptr) throw()
  { 
return ::operator delete(pMemory, ptr); }

  
// nothrow new/delete
  static void* operator new(std::size_t size, const std::nothrow_t& nt) throw()
  { 
return ::operator new(size, nt); }
  
static void operator delete(void *pMemory, const std::nothrow_t&throw()
  { ::
operator delete(pMemory); }
};

class Widget: public StandardNewDeleteForms {           // inherit std forms
public:
   
using StandardNewDeleteForms::operator new;          // make those
   using StandardNewDeleteForms::operator delete;       // forms visible

   
static void* operator new(std::size_t size,          // add a custom
                             std::ostream& logStream)   // placement new
     throw(std::bad_alloc);

   
static void operator delete(void *pMemory,           // add the corres-
                               std::ostream& logStream) // ponding place-
    throw();                                            // ment delete
  
//..
};
posted on 2010-06-16 00:13 Justin.H 阅读(788) 评论(0)  编辑 收藏 引用 所属分类: Effective C++ 炒冷饭

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理