简体   繁体   English

Qt QList-removeAll释放内存

[英]Qt QList - removeAll deallocating memory

I have a QList of MyClass pointers like this: 我有一个像这样的MyClass指针的QList

QList<MyClass*> myList;

When I call myList.removeAll(someObjPtr); 当我调用myList.removeAll(someObjPtr); it doesn't just remove the pointers from the QList , it calls delete on them internally. 它不仅从QList删除指针,还内部调用了delete。 Is there a way to get around this or is there an alternative QList method that would just remove the elements without deallocating them? 有没有办法解决这个问题,或者有替代的QList方法可以删除元素而不分配它们?

EDIT: Internals of removeAll: 编辑: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;
}

As you can see it calls node_destruct, which does this: 如您所见,它调用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();
}

As you see, there is a delete being called. 如您所见,有一个删除被调用。

QList has nothing to do with Qt 3's QPtrList . QList与Qt 3的QPtrList没有QPtrList

None of the QList methods interpret stored pointers in a special way. 没有QList方法以特殊方式解释存储的指针。 You must be testing it wrongly. 您必须对它进行了错误的测试。 For example, the code below happily leaks two C instances and never deletes them. 例如,以下代码愉快地泄漏了两个C实例,并且从不删除它们。

Perhaps you were thinking of qDeleteAll from QtAlgorithms ? 也许您在考虑QtAlgorithmsqDeleteAll This one will delete the instances. 删除实例。

Note that QList 's implementation may allocate per-item memory to store your instances in, and will free that memory when appropriate. 请注意, QList的实现可以分配每个项目的内存以在其中存储您的实例,并在适当时释放该内存。 In no case will QList implementation delete a pointer that you store in the list: the only way QList interprets the stored data is via its type, and then it's only to decide whether the items are memory-movable, and whether they fit into a void* or do they need to be individually allocated. QList实现决不会删除您存储在列表中的指针: QList解释存储的数据的唯一方法是通过其类型,然后才可以确定这些项是否可移动存储以及它们是否适合void*还是需要单独分配它们。 In fact, all pointer types are stored in QList as if it were a QVector , with a bit of room added at the beginning and the end to make push_front and push_back have amortized O(1) cost. 实际上, 所有指针类型都存储在QList ,就像它是QVector ,在开头和结尾都添加了一些空间,使push_frontpush_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 does not delete the objects pointed to by QLists of pointers. node_destruct不会删除指针QList指向的对象。 If you look closely, it only deletes n->v for large and static types. 如果仔细观察,它只会删除大型和静态类型的n->v QList internally allocates large and static types on the heap, so the delete is necessary. QList在内部在堆上分配大型和静态类型,因此删除是必需的。

For pointer types, the QTypeInfo<T> specialization is: 对于指针类型, QTypeInfo<T>专长是:

template <typename T>
class QTypeInfo<T*>
{
public:
    enum {
        isPointer = true,
        isComplex = false,
        isStatic = false,
        isLarge = false,
        isDummy = false
    };
};

As you see, pointers are neither large nor static, so are not deleted 如您所见,指针既不大也不静态,因此不会被删除

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM