QObject实例池

时间:2014-07-02 03:53:33

标签: c++ qt gcc qt4 qsharedpointer

我遇到了一个问题,我不确定如何解决..

我们有通用对象池。请求对象时,池会将QSharedPointer返回到第一个可用实例,并指定自定义Deleter。当QSharedPointer实例引用计数为0时,删除器仅将对象返回到池。 一切都适用于普通物体。当在Qt 5中编译时,它也适用于QObject后继者。

但是,如果在Qt 4.6中编译 - 问题就开始了:第二次请求相同的对象时 - 应用程序退出时出现错误:

  

" QSharedPointer:指针xxx已经有引用计数"

我写了简单的测试:

QObject* obj = new QObject();
QSharedPointer<QObject> p(obj, deleter); // deleter here does nothing
p.clear();
QSharedPointer<QObject> p2(obj, deleter); // this crashes the app

当在Qt 4.6中编译时,肯定会失败。再次:在QT 5.x中工作正常。

查看Qt源代码,当QObject用作QObject参数时,它会在QSharedPointer中初始化内部参考计数器。这样做是为了确保没有两个智能指针可以指向同一个对象,它只会在析构函数中重置。

QObject实例被包装到智能指针中时,Qt5不检查ref计数器值,因此它可以工作。

有没有人知道旧Qt版本的解决方法?是否可以完全重置内部Qt状态,包括ref计数器?任何提示都非常受欢迎。

2 个答案:

答案 0 :(得分:0)

假设你有池以避免内存分配和释放,你应该只分配一次内存,然后在你请求并返回&#34; new&#34;时显式调用构造函数和析构函数。对象

/* deleter calls destructor explicitly when return object to pool */
void deleter(QObject *object) {
    object->~QObject();
    mark_as_available();
}

/* allocate (one object) pool memory without calling constructor*/
QObject *object = ::operator new(sizeof(QObject));

/* request object - calling constructor on already allocated memory */
mark_as_taken();
return QSharedPointer(::new (object) QObject, &deleter);

/* deallocate pool memory without calling destructor */
::operator delete(object);

答案 1 :(得分:0)

只允许您一次从QSharedPointer创建QObject 后者,您将需要复制现有的QSharedPointer实例

根据Qt 4 and 5文档:

  

QSharedPointer 将在其超出范围时删除它持有的指针,前提是没有其他QSharedPointer对象引用该指针。

所以您的示例行为如下:

QObject* obj = new QObject();
QSharedPointer<QObject> p(obj, deleter); // deleter here does attach to "obj"
p.clear(); //this does cause delete of "obj"
QSharedPointer<QObject> p2(obj, deleter); // using deleted pointer will cause crash (if you are lucky XD)

使用QWeakPointer不会删除QObject和断言:

  

“ QSharedPointer:指针xxx已经具有引用计数”

是为了确保您不会意外创建多个删除器(这对我来说很安全,我在使用QSharedPointer,但意思是QWeakPointer),但有时确实会造成麻烦。