QTextCodec相关的new、delete问题一则

53 篇文章 6 订阅

在 Qt之QTextCodec乱谈 一文中我们提到这个一样例子

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QTextCodec * codec = new DbzhangCodec;
    QTextCodec::setCodecForCStrings(codec);
    qDebug()<<QString("hello world!");
    return 0;
}

其中,DbzhangCodec是QTextCodec的一个派生类。这儿使用了 new ,但是却没有相应地使用 delete,可是却没有造成内存泄漏,原因何在?

构造与析构函数

从构造函数开始看起:当对象被创建时,它会将指向自己的指针添加到一个static的列表中。

/*!
    Constructs a QTextCodec, and gives it the highest precedence. The
    QTextCodec should always be constructed on the heap (i.e. with \c
    new). Qt takes ownership and will delete it when the application
    terminates.
*/
QTextCodec::QTextCodec()
{
...
    all->prepend(this);
}

其中:all是一个static的列表

static QList<QTextCodec*> *all = 0;

看一下析构函数

/*!
    Destroys the QTextCodec. Note that you should not delete codecs
    yourself: once created they become Qt's responsibility.
*/
QTextCodec::~QTextCodec()
{
    if (all) {
        all->removeAll(this);
...
    }
}

上面的两段注释明确告诉我们:对象必须分配在heap中,而且由Qt负责在程序退出之前删除它。

可是,删除操作是怎么实现的呢?

QTextCodecCleanup

class QTextCodecCleanup
{
public:
    ~QTextCodecCleanup();
};

/*
    Deletes all the created codecs. This destructor is called just
    before exiting to delete any QTextCodec objects that may be lying
    around.
*/
QTextCodecCleanup::~QTextCodecCleanup()
{
...
    for (QList<QTextCodec *>::const_iterator it = all->constBegin()
            ; it != all->constEnd(); ++it) {
        delete *it;
    }
    delete all;
    all = 0;
...
}

这是一个很简单的类,只定义了一个析构函数:负责删除列表 all 中的所有QTextCodec对象。

要使得这个析构函数被调用,显然需要构造一个QTextCodecCleanup对象,这是通过:

Q_GLOBAL_STATIC(QTextCodecCleanup, createQTextCodecCleanup)

实现的

Q_GLOBAL_STATIC

这个宏定义在 qglobal.h 这个头文件内(根据你所用的Qt的版本不同,你的源码初看起来与此可能有很大不同)。

#define Q_GLOBAL_STATIC(TYPE, NAME)   \
    static TYPE *NAME()               \
    {                                 \
        static QGlobalStatic<TYPE > thisGlobalStatic        \
               = { Q_BASIC_ATOMIC_INITIALIZER(0), false };  \
        if (!thisGlobalStatic.pointer && !thisGlobalStatic.destroyed) { \
            TYPE *x = new TYPE;                                         \
            if (!thisGlobalStatic.pointer.testAndSetOrdered(0, x))      \
                delete x;                                               \
            else                                                        \
                static QGlobalStaticDeleter<TYPE > cleanup(thisGlobalStatic); \
        }                                                               \
        return thisGlobalStatic.pointer;                                \
    }

由于考虑了线程安全性,这个宏看起来还真乱,其实呢,也就是一个静态的函数

static QTextCodecCleanup * createQTextCodecCleanup()
{
}

该函数内,创建了两个静态的对象

static QGlobalStatic<QTextCodecCleanup> thisGlobalStatic;
static QGlobalStaticDeleter<QTextCodecCleanup> cleanup(thisGlobalStatic);

thisGlobalStatic 中保存有 QTextCodecCleanup 对象的指针(并作为函数的返回值返回);cleanup 析构时将析构掉该指针所指向的对象。


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值