析构时候清除pointer

template <typename T>

struct QScopedPointerDeleter

{

    static inline void cleanup(T *pointer)

    {

        // Enforce a complete type.

        // If you get a compile error here, read the secion on forward declared

        // classes in the QScopedPointer documentation.

//检查类型是否完整,编译期间检查

        typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ];

        (void) sizeof(IsIncompleteType);

        delete pointer;

    }

};

template <typename T>

struct QScopedPointerArrayDeleter

{

    static inline void cleanup(T *pointer)

    {

        // Enforce a complete type.

        // If you get a compile error here, read the secion on forward declared

        // classes in the QScopedPointer documentation.

        typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ];

        (void) sizeof(IsIncompleteType);

        delete [] pointer;

    }

};

struct QScopedPointerPodDeleter

{

    static inline void cleanup(void *pointer) { if (pointer) qFree(pointer); }

};

template <typename T, typename Cleanup = QScopedPointerDeleter<T> >

class QScopedPointer

{

#ifndef Q_CC_NOKIAX86

    typedef T *QScopedPointer:: *RestrictedBool;

#endif

public:

    explicit inline QScopedPointer(T *p = 0) : d(p)

    {

    }

    inline ~QScopedPointer()

    {

        T *oldD = this->d;

        Cleanup::cleanup(oldD);

        this->d = 0;

    }

    inline T &operator*() const

    {

        Q_ASSERT(d);

        return *d;

    }

    inline T *operator->() const

    {

        Q_ASSERT(d);

        return d;

    }

    inline bool operator!() const

    {

        return !d;

    }

#if defined(Q_CC_NOKIAX86) || defined(Q_QDOC)

    inline operator bool() const

    {

        return isNull() ? 0 : &QScopedPointer::d;

    }

#else

    inline operator RestrictedBool() const

    {

        return isNull() ? 0 : &QScopedPointer::d;

    }

#endif

    inline T *data() const

    {

        return d;

    }

    inline bool isNull() const

    {

        return !d;

    }

    inline void reset(T *other = 0)

    {

        if (d == other)

            return;

        T *oldD = d;

        d = other;

        Cleanup::cleanup(oldD);

    }

    inline T *take()

    {

        T *oldD = d;

        d = 0;

        return oldD;

    }

    inline void swap(QScopedPointer<T, Cleanup> &other)

    {

        qSwap(d, other.d);

    }

typedef T *pointer;

protected:

    T *d;

private:

    Q_DISABLE_COPY(QScopedPointer)

};

template <class T, class Cleanup>

inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)

{

    return lhs.data() == rhs.data();

}

template <class T, class Cleanup>

inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)

{

    return lhs.data() != rhs.data();

}

template <class T, class Cleanup>

Q_INLINE_TEMPLATE void qSwap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2)

{ p1.swap(p2); }

template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> >

class QScopedArrayPointer : public QScopedPointer<T, Cleanup>

{

public:

    explicit inline QScopedArrayPointer(T *p = 0)

        : QScopedPointer<T, Cleanup>(p)

    {

    }

    inline T &operator[](int i)

    {

        return this->d[i];

    }

    inline const T &operator[](int i) const

    {

        return this->d[i];

    }

private:

    Q_DISABLE_COPY(QScopedArrayPointer)

};


#define Q_DISABLE_COPY(Class) \

    Class(const Class &); \

    Class &operator=(const Class &);


声明拷贝和赋值函数为私有


--------------------------------

参考

C++ template Day Day Up 第四天 Boost::checked_delete

//DeleteObject.h

QScopedPointer  源码剖析_#includeclass Item;

QScopedPointer  源码剖析_#include

QScopedPointer  源码剖析_#includeclass DeleteObject

QScopedPointer  源码剖析_编译错误_04{

QScopedPointer  源码剖析_编译错误_05public:

QScopedPointer  源码剖析_编译错误_05    DeleteObject(void);

QScopedPointer  源码剖析_编译错误_05public:

QScopedPointer  源码剖析_编译错误_05 ~DeleteObject(void);

QScopedPointer  源码剖析_编译错误_05

QScopedPointer  源码剖析_编译错误_05 void DeleteItem(Item* p);

QScopedPointer  源码剖析_#include_11};

QScopedPointer  源码剖析_#include

//DeleteObject.cpp

QScopedPointer  源码剖析_#include#include "StdAfx.h"

QScopedPointer  源码剖析_#include#include "DeleteObject.h"

QScopedPointer  源码剖析_#include#include <boost/checked_delete.hpp>

QScopedPointer  源码剖析_#include

QScopedPointer  源码剖析_#includeDeleteObject::DeleteObject(void)

QScopedPointer  源码剖析_编译错误_04{

QScopedPointer  源码剖析_#include_11}

QScopedPointer  源码剖析_#include

QScopedPointer  源码剖析_#includeDeleteObject::~DeleteObject(void)

QScopedPointer  源码剖析_编译错误_04{

QScopedPointer  源码剖析_#include_11}

QScopedPointer  源码剖析_#include

QScopedPointer  源码剖析_#includevoid DeleteObject::DeleteItem( Item* p )

QScopedPointer  源码剖析_编译错误_04{

QScopedPointer  源码剖析_编译错误_05    delete p;

QScopedPointer  源码剖析_#include_11}

//item.h

QScopedPointer  源码剖析_#include#include <iostream>

QScopedPointer  源码剖析_#include

QScopedPointer  源码剖析_#includeclass Item

QScopedPointer  源码剖析_编译错误_04{

QScopedPointer  源码剖析_编译错误_05public:

QScopedPointer  源码剖析_编译错误_05 ~Item()

QScopedPointer  源码剖析_#include_35 {

QScopedPointer  源码剖析_编译错误_05        std::cout<<"Item destruction ";

QScopedPointer  源码剖析_编译错误_37    }

QScopedPointer  源码剖析_#include_11};

//main.cpp

#include "DeleteObject.h"

#include "Item.h"

DeleteObject del;

del.DeleteItem(new Item);

/////////////////////////////////

结果Item的析构函数没有被调用~

这是因为DeleteObject并不知道Item的详细定义,这是C++中一个很危险的错误!(还好编译器一般都给warning)

怎么解决这个问题呢?

利用Boost库中的checked_delete

定义如下:

QScopedPointer  源码剖析_#includetemplate<class T> inline void checked_delete(T * x)

QScopedPointer  源码剖析_编译错误_04{

QScopedPointer  源码剖析_编译错误_05 // intentionally complex - simplification causes regressions

QScopedPointer  源码剖析_编译错误_05    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];

QScopedPointer  源码剖析_编译错误_05    (void) sizeof(type_must_be_complete);

QScopedPointer  源码剖析_编译错误_05    delete x;

QScopedPointer  源码剖析_#include_11}

QScopedPointer  源码剖析_#include

QScopedPointer  源码剖析_#includetemplate<class T> inline void checked_array_delete(T * x)

QScopedPointer  源码剖析_编译错误_04{

QScopedPointer  源码剖析_编译错误_05    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];

QScopedPointer  源码剖析_编译错误_05    (void) sizeof(type_must_be_complete);

QScopedPointer  源码剖析_编译错误_05    delete [] x;

QScopedPointer  源码剖析_#include_11}

可以看到利用C的一个语法——数组长度必须大于零,来解决这个问题,typedef是发生在编译期,而sizeof同样是在编译期,所以这两行代码不会对程序的效率空间等等产生任何影响,只会在上面所举的例子发生的时候报编译错误。

现在将代码改为:

QScopedPointer  源码剖析_#includevoid DeleteObject::DeleteItem( Item* p )

QScopedPointer  源码剖析_编译错误_04{

QScopedPointer  源码剖析_编译错误_05    boost::checked_delete(p);

QScopedPointer  源码剖析_#include_11}