有效的C ++:第52项以及如何避免隐藏所有正常运算符new&删除版本

时间:2010-08-13 13:32:17

标签: c++ memory-management

在Myer的Effective C ++的第52项(自定义新增和删除)结束时,他讨论了如何在实现自定义版本时避免隐藏正常的新版本和删除版本,如下所示:

  

如果你宣布任何运营商新闻   上课,你会隐藏所有这些标准   形式。除非你的意思是预防   类客户使用这些表格,   一定要把它们提供给   除了任何自定义操作员新   你创建的表单。对于每个运营商   当然,你可以使用新的   一定要提供相应的   运营商删除。如果你想   这些功能在通常的行为   方式,只是你的特定类   版本称为全球版本。

     

一种简单的方法是创建一个   包含所有法线的基类   新形式和删除:

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); }

};
  

想要扩充的客户   标准表格与自定义表格可以   然后只使用继承和使用   声明(见第33项)获得   标准表格:

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

  ...

};

为什么要去创建类StandardNewDeleteForms,继承它,然后在派生类中说:

using StandardNewDeleteForms::operator new;
using StandardNewDeleteForms::operator delete;

你能不能完全放弃基类,只需写入Widget类:

using ::operator new;
using ::operator delete;

实现同样的目标?

3 个答案:

答案 0 :(得分:2)

这实际上是一个无操作using。他只是展示了基类new / delete的实现,它将复制正常行为。

通常,如果您要创建自定义newdelete,那么您将更改该基类中的行为,而using ::operator new;将不再相同。他没有在他的例子中那样做,所以发生的事情不太清楚。

答案 1 :(得分:0)

首先,不允许using ::operator new;,因为它不是父类的成员。

其次,由于大多数时候全球新品不适合超载:  1.你将使用使用或不使用此操作符的库,造成混乱;  2.您可能希望为不同类型的对象使用不同的新/删除代码;

这个项目背后的想法是你可以改变继承父类的类的新/删除行为,允许改变整组类的分配策略。

答案 2 :(得分:0)

我正在阅读同一本书,我想知道完全一样的事情!

管理using的规则似乎取决于上下文:

在命名空间中使用时,它允许您将其他命名空间(包括全局命名空间)中的成员提取到新命名空间(source)中:

 void f();
 namespace A {
   void g();
 }
 namespace X {
   using ::f;  // global f is now visible as ::X::f
   using A::g; // A::g is now visilbe as ::X::g
 }
 void h()
 {
   X::f(); // calls ::f
   X::g(); // calls A::g
 }

但是,在类定义中使用时为(source):

using nested-name-specifier

然后

  

nested-name-specifier必须命名正在定义的基类。