我遇到了一个问题,我不确定如何解决..
我们有通用对象池。请求对象时,池会将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计数器?任何提示都非常受欢迎。
答案 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
实例
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
),但有时确实会造成麻烦。