http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Checked_delete

试了一下,果然是如此。在只见声明,未见定义的情况下用delete确实不会调用析构函数。

 

Intent

Increase safety of delete expression.

Also Known As

Motivation and Sample Code

The C++ Standard allows, in 5.3.5/5, pointers to incomplete class types to be deleted with a delete-expression. When the class has a non-trivial destructor, or a class-specific operator delete, the behavior is undefined. Some compilers issue a warning when an incomplete type is deleted, but unfortunately, not all do, and programmers sometimes ignore or disable warnings.

In the following example, main.cpp can see the definition of Object. However, main() calls delete_object() -- defined in deleter.cpp -- which does not see the definition of Object, but only predeclares it. Calling "delete" on a partially defined type like this is undefined behavior which some compilers do not flag.

////////////////////
// File: deleter.hpp
////////////////////
// declares but does not define Object
class Object;
void delete_object(Object* p);

////////////////////
// File: deleter.cpp
////////////////////
#include "deleter.hpp"

// Deletes an Object without knowing its definition
void delete_object(Object* p) { delete p; }

////////////////////
// File: object.hpp
////////////////////
struct Object
{
// this user-defined destructor won't be called when delete
// is called on a partially-defined (i.e., predeclared) Object
~Object() {
// ...
}
};

////////////////////
// File: main.cpp
////////////////////
#include "deleter.hpp"
#include "object.hpp"

int main() {
Object* p = new Object;
delete_object(p);
}

Solution and Sample Code

The checked delete idiom does not allow deletion of objects of partially defined type, but instead forces a compiler error if such a delete is invoked. The following is the implementation of checked_delete function template in boost. It forces a compiler error by declaring an array of negative elements if type T is not defined i.e. only a forward declaration is present. The use of sizeof() on a partially-defined type will either trigger a compiler error, or else return zero, which will lead to a compiler error for the illegal negative-size array.

template<class T> 
inline void checked_delete(T * x)
{
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}
template<class T>
struct checked_deleter : std::unary_function <T *, void>
{
void operator()(T * x) const
{
boost::checked_delete(x);
}
};

The supplied function and class templates can be used to prevent these problems, as they require a complete type, and cause a compilation error otherwise. It is similarly applicable to array delete operator as well.

NOTE: std::auto_ptr does not use anything equivalent to checked delete. Therefore, instantiating std::auto_ptr using an incomplete type may cause undefined behavior in its destructor if at the point of declaration of the std::auto_ptr the template parameter type is not fully defined.

Known Uses

Related Idioms

References

http://www.boost.org/libs/utility/checked_delete.html