[英]Qt QList - removeAll deallocating memory
我有一個像這樣的MyClass
指針的QList
:
QList<MyClass*> myList;
當我調用myList.removeAll(someObjPtr);
它不僅從QList
刪除指針,還內部調用了delete。 有沒有辦法解決這個問題,或者有替代的QList
方法可以刪除元素而不分配它們?
編輯:removeAll的內部:
template <typename T>
Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t)
{
int index = indexOf(_t);
if (index == -1)
return 0;
const T t = _t;
detach();
Node *i = reinterpret_cast<Node *>(p.at(index));
Node *e = reinterpret_cast<Node *>(p.end());
Node *n = i;
node_destruct(i);
while (++i != e) {
if (i->t() == t)
node_destruct(i);
else
*n++ = *i;
}
int removedCount = e - n;
d->end -= removedCount;
return removedCount;
}
如您所見,它調用node_destruct,它執行以下操作:
template <typename T>
Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *n)
{
if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) delete reinterpret_cast<T*>(n->v);
else if (QTypeInfo<T>::isComplex) reinterpret_cast<T*>(n)->~T();
}
如您所見,有一個刪除被調用。
QList
與Qt 3的QPtrList
沒有QPtrList
。
沒有QList
方法以特殊方式解釋存儲的指針。 您必須對它進行了錯誤的測試。 例如,以下代碼愉快地泄漏了兩個C實例,並且從不刪除它們。
也許您在考慮QtAlgorithms
的qDeleteAll
? 這將刪除實例。
請注意, QList
的實現可以分配每個項目的內存以在其中存儲您的實例,並在適當時釋放該內存。 QList
實現決不會刪除您存儲在列表中的指針: QList
解釋存儲的數據的唯一方法是通過其類型,然后才可以確定這些項是否可移動存儲以及它們是否適合void*
還是需要單獨分配它們。 實際上, 所有指針類型都存儲在QList
,就像它是QVector
,在開頭和結尾都添加了一些空間,使push_front
和push_back
攤銷了O(1)成本。
#include <QtCore>
struct C {
static int ctr;
C() { ctr ++; }
~C() { ctr --; qDebug() << (void*)this << "C instance destructed"; }
};
int C::ctr;
int main() {
auto c1 = new C, c2 = new C;
auto list1 = QList<C*>() << c1 << c2;
list1.removeAll(c1); // doesn't delete the pointed-to objects
list1.removeAll(c2);
Q_ASSERT(list1.isEmpty());
Q_ASSERT(C::ctr == 2);
// we'll happily leak both instances above
auto list2 = QList<C*>() << new C << new C << new C;
qDeleteAll(list2); // invokes delete on all objects
Q_ASSERT(C::ctr == 2);
}
node_destruct
不會刪除指針QList指向的對象。 如果仔細觀察,它只會刪除大型和靜態類型的n->v
。 QList在內部在堆上分配大型和靜態類型,因此刪除是必需的。
對於指針類型, QTypeInfo<T>
專長是:
template <typename T>
class QTypeInfo<T*>
{
public:
enum {
isPointer = true,
isComplex = false,
isStatic = false,
isLarge = false,
isDummy = false
};
};
如您所見,指針既不大也不靜態,因此不會被刪除
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.