天天看点

checked_delete/checked_array_delete

  在boost的智能指针中析构时都用到了checked_delete 和checked_array_delete,为什么不简单地delete呢?

  在头文件”boost/checked_delete.hpp”定义了两个函数模板,checked_delete 和 checked_array_delete, 以及两个类模板,checked_deleter 和 checked_array_deleter。他们作用是什么呢?

官方解释:

  C++标准的 5.3.5/5 节中允许通过一个 delete 表达式删除指向不完全类的指针。如果该类有一个非平凡的析构函数,或者有一个类相关的 delete 操作符,那么其行为就是无定义的。有些编译器会在删除不完全类型时给出警告,但不幸的是,不是所有编译器都这样,而且程序员有时也会忽略或禁止警告。

  一个尤其麻烦的情况是以一个不完全类型实例化一人智能指针的析构函数,如 boost::scoped_ptr::~scoped_ptr。这通常会引起难以跟踪的错误。

  本库提供的函数和类模板可用于防止这些问题,它们要求一个完全的类型,否则引发一个编译错误。

  如果T是Incomplete Types,sizeof(T)将返回0,此时checked_delete将因为声明-1个成员的数组而引发错误。

  什么是Incomplete Types?

  An incomplete type is a type that describes an identifier but lacks information needed to determine the size of the identifier. An “incomplete type” can be:

  A structure type whose members you have not yet specified.

  A union type whose members you have not yet specified.

  An array type whose dimension you have not yet specified.

  The void type is an incomplete type that cannot be completed. To complete an incomplete type, specify the missing information. The following examples show how to create and complete the incomplete types.

struct student;      // incomplete type
struct student
{
    int num;
}                 // student structure now completed 

int a[];            // incomplete type
int a[];          // now completed
           

  checked_delete和checked_array_delete代码如下:

template<class T> inline void checked_delete(T * x)
{
  typedef char type_must_be_complete[ sizeof(T)? : - ];
  (void) sizeof(type_must_be_complete);
  delete x;
}

template<class T> inline void checked_array_delete(T * x)
{
  typedef char type_must_be_complete[ sizeof(T)? : - ];
  (void) sizeof(type_must_be_complete);
  delete [] x;
}
           

  来看stackoverflow上的一个例子:

  The most common example of an incomplete type is one that has only been declared:

// this file does not include the definition of foo
class foo;
void bad(foo *f)
{
    delete f;  // undefined behavior if there exists foo::~foo
}
           

  In reality, the definition of foo may look like this:

class foo
{
public:
    ~foo() { ... };
};
           

  But if the top code has not ‘seen’ the class definition and just sees the class declaration, the code will compile.