一、描述

QList<T> 是 Qt 的通用容器类之一。它将其项目存储在相邻的内存位置并提供基于索引的快速访问。QVector<T> 在 Qt 5 中曾经是一个不同的类,但在Qt6它是 QList 的一个别名。

QList<T> 和 QVarLengthArray<T> 提供类似的 API 和功能。它们通常可以互换。

  • QList 应该是默认首选。
  • QVarLengthArray 提供了一个在堆栈上保留空间的数组,但如果需要,可以动态地增长到堆上。用于通常较小的短寿命容器是很好的。

由于隐式共享,使用非常量运算符和函数可能会导致 QList 对数据进行深度复制。

QList 的值类型必须是可赋值的数据类型。这涵盖了大多数常用的数据类型,但编译器不会允许将 QWidget 存储为值(可以存储一个 QWidget *)。

最大大小

QList 的最大大小取决于体系结构。大多数 64 位系统可以分配超过 2 GB 的内存,典型限制为 2^63 字节。实际值还取决于管理数据块所需的开销。因此,可以预期最大大小为 2 GB 减去 32 位平台上的开销,以及 2^63 字节减去 64 位平台上的开销。可以存储在 QList 中的元素数是此最大大小除以存储元素的大小。

内存不足的情况

当内存分配失败时,QList 使用 Q_CHECK_PTR 宏,如果应用程序编译时带有异常支持,它会抛出 std::bad_alloc 异常。如果异常被禁用,则内存不足是未定义的行为。

操作系统可能会对持有大量已分配内存的应用程序施加进一步限制,尤其是大的连续块。此类考虑、此类行为的配置或任何缓解措施超出了 Qt API 的范围。


二、成员函数

1、void replace(qsizetype i, QList::parameter_type value)

      void replace(qsizetype i, QList::rvalue_ref value)

用值替换索引位置 i 处的项目。i 必须是列表中的有效索引位置(即 0 <= i < size())。

2、插入数据

QList::iterator insert(qsizetype i, QList::parameter_type value)
QList::iterator insert(qsizetype i, QList::rvalue_ref value)

在列表中的索引位置 i 处插入值。 如果 i = 0,则该值将添加到最前面。如果 i = size(),则将该值追加到列表中。

对于大型列表,此操作可能很慢,因为它需要将索引 i 及以上的所有项目在内存中进一步移动一个位置。 如果想要一个提供快速 insert() 函数的容器类,请改用 std::list

QList::iterator insert(qsizetype i, qsizetype count, QList::parameter_type value)

在列表中的索引位置 i 处插入值的 count 个副本。

QList<double> list;
list << 2.718 << 1.442 << 0.4342;
list.insert(1, 3, 9.9);
// list: [2.718, 9.9, 9.9, 9.9, 1.442, 0.4342]

QList::iterator insert(QList::const_iterator before, QList::parameter_type value)
QList::iterator insert(QList::const_iterator before, QList::rvalue_ref value)

重载函数。在之前的迭代器指向的项目前插入值。返回指向插入项的迭代器。

    QList<int> list;
    auto insertIt = std::back_inserter(list);
    for(int i = 0;i < 7;++i)
    {
        *insertIt = i;
        ++insertIt;
    }
    qDebug()<<list;
    auto it = list.begin();
    it += 3;
    qDebug()<<*it;
    auto it2 = list.insert(it,8);
    qDebug()<<list;
    qDebug()<<*it2;

 QList::iterator insert(QList::const_iterator before, qsizetype count, QList::parameter_type value)

在迭代器之前指向的项之前插入值的 count 个副本。 返回指向第一个插入项的迭代器。

3、template <typename Args> QList::reference emplaceBack(Args &&... args)

     template <typename Args> QList::reference emplace_back(Args &&... args)

在容器的末尾添加一个新元素。这个新元素是使用 args 作为构造参数就地构造的。返回对新元素的引用。

QList<QString> list{"one", "two"};
list.emplaceBack(3, 'a'); //构造函数:QString(qsizetype size, QChar ch)
qDebug() << list;  // list: ["one", "two", "aaa"]

也可以使用返回的引用访问新创建的对象:

QList<QString> list;
auto &ref = list.emplaceBack();
ref = "one";
// list: ["one"]

4、void prepend(QList::parameter_type value)

     void prepend(QList::rvalue_ref value)

     void push_front(QList::parameter_type value)

     void push_front(QList::rvalue_ref value)

在列表的开头插入值。

通常这个操作是比较快的。 QList 能够在列表数据的开头分配额外的内存并在该方向上增长,而无需在每个操作上重新分配或移动数据。 但是,如果想要一个在前面插入复杂度为O(1)的容器类,请改用 std::list

5、构造函数

QList()

QList(const QList<T> &other)

复杂度为O(1),因为 QList 是隐式共享的。 这使得从函数返回 QList 的速度非常快。 如果共享实例被修改,它将被复制(写时复制),这需要线性时间(O(n))。

QList(QList<T> &&other)

QList(InputIterator first, InputIterator last)

使用迭代器构造。

QList(std::initializer_list<T> args)

QList(qsizetype size, QList::parameter_type value)

构造一个初始大小为 size 元素的列表。每个元素都用value初始化。

QList(qsizetype size)

构造一个初始大小为 size 元素的列表。元素使用默认构造的值进行初始化。

6、在末尾追加元素

void append(QList::parameter_type value)

此操作相对较快,因为 QList 通常分配比所需更多的内存,因此它可以增长而无需每次重新分配整个列表。

void append(QList::rvalue_ref value)

QList<QString> list;
list.append("one");
list.append("two");
QString three = "three";
list.append(std::move(three));
// list: ["one", "two", "three"]
// three: ""

void append(const QList<T> &value)

void append(QList<T> &&value)

void push_back(QList::parameter_type value)

void push_back(QList::rvalue_ref value)

QList<T> & operator+=()

7、QList::const_reference at(qsizetype i) const

      QList::const_reference operator[](qsizetype i) const

不会深拷贝。

      QList::reference operator[](qsizetype i)

使用非常量运算符会导致 QList 进行深拷贝。

8、 begin() / cbegin()             constBegin() / constEnd()        end() / cend()   

起始迭代器 / 常起始迭代器        尾迭代器 / 常尾迭代器。

         crbegin() / crend()

反向迭代器。

    QList<int> list;
    list << 1<<2<<3;
    for(auto it = list.crbegin();it != list.crend();++it)
        qDebug()<<(*it);// 3 2 1

9、qsizetype capacity()

返回可以存储在列表中而不强制重新分配的最大项目数。

此函数的唯一目的是提供一种微调 QList 内存使用的方法。通常很少需要调用此函数。如果想知道列表中有多少项应调用 size()。

10、void clear()

从列表中删除所有元素。但列表申请的内存还在。

    QList<ceshi> list;
    list << 1<<2<<3;
    qDebug()<<list.capacity();
    list.clear();
    qDebug()<<list.capacity();

11、QList::const_pointer constData()

返回指向存储在列表中的数据的常量指针。指针可用于访问列表中的项目。

此函数主要用于将列表传递给接受普通 C++ 数组的函数。

12、const T & constFirst() / const T & constLast()   

返回对列表中第一项 / 最后一项的常引用。

13、template <typename AT> bool contains(const AT &value)

是否包含值。此函数要求值类型具有 operator==() 的实现。

14、template <typename AT> qsizetype count(const AT &value)

返回值在列表中出现的次数。此函数要求值类型具有 operator==() 的实现。

15、data()

返回指向存储在列表中的数据的指针。

此函数主要用于将列表传递给接受普通 C++ 数组的函数。

QList<int> list(10);
int *data = list.data();
for (qsizetype i = 0; i < 10; ++i)
    data[i] = 2 * i;

16、template <typename Args> QList::iterator emplace(qsizetype i, Args &&... args)

       template <typename Args> QList::iterator emplace(QList::const_iterator before, Args &&... args) 

在位置 i 插入一个新元素。这个新元素是使用 args 作为构造参数就地构造的。

返回一个指向新元素的迭代器。

QList<QString> list{"a", "ccc"};
list.emplace(1, 2, 'b');
// list: ["a", "bb", "ccc"]

17、bool empty()

提供此功能是为了兼容 STL。等价于isEmpty()。

18、bool endsWith(QList::parameter_type value) / bool startsWith(QList::parameter_type value)

此列表是否不为空且其最后一项 / 第一项 等于 value。

19、 QList::iterator erase(QList::const_iterator pos)

        QList::iterator erase(QList::const_iterator begin, QList::const_iterator end)

从列表中移除迭代器 pos 指向的项目,并返回一个迭代器到列表中的下一个项目。

元素删除但未减少列表内存。

20、QList<T> & fill(QList::parameter_type value, qsizetype size = -1)

为列表中的所有项目赋值。 如果 size 不同于 -1(默认值),则列表会预先调整为 size。

QList<QString> list(3);
list.fill("Yes");
// list: ["Yes", "Yes", "Yes"]

list.fill("oh", 5);
// list: ["oh", "oh", "oh", "oh", "oh"]

21、first()、front() / last()、back()

首个元素 / 最后一个元素。

22、QList<T> first(qsizetype n) / QList<T> last(qsizetype n)

返回包含此列表的前 n 个 / 后 n 个元素的子列表。

23、template <typename AT> qsizetype indexOf(const AT &value, qsizetype from = 0)

返回列表中第一次出现 value 的索引位置,从索引位置开始向前搜索。如果没有匹配项,则返回 -1。此函数要求值类型具有 operator==() 的实现。

QList<QString> list;
list << "A" << "B" << "C" << "B" << "A";
list.indexOf("B");            // returns 1
list.indexOf("B", 1);         // returns 1
list.indexOf("B", 2);         // returns 3
list.indexOf("X");            // returns -1

24、template <typename AT> qsizetype lastIndexOf(const AT &value, qsizetype from = -1)

返回列表中最后一次出现值的索引位置,从索引位置开始向后搜索。如果 from 是 -1(默认值),则搜索从最后一项开始。 如果没有匹配项,则返回 -1。此函数要求值类型具有 operator==() 的实现。

QList<QString> list;
list << "A" << "B" << "C" << "B" << "A";
list.lastIndexOf("B");        // returns 3
list.lastIndexOf("B", 3);     // returns 3
list.lastIndexOf("B", 2);     // returns 1
list.lastIndexOf("X");        // returns -1

25、QList<T> mid(qsizetype pos, qsizetype length = -1)

返回包含此列表中元素的子列表,从位置 pos 开始。 如果 length 为 -1(默认),则包含 pos 之后的所有元素; 否则包括 length 个元素(如果少于length个元素,则返回所有剩余元素)。

26、void move(qsizetype A, qsizetype B)

将A位置的元素移动到B位置。

27、void pop_back() / void removeLast()

删除列表中的最后一项,但未清理列表的空间。

28、void pop_front() / void removeFirst()

删除列表中的第一项,但未清理列表的空间。

29、void remove(qsizetype i, qsizetype n = 1)

从列表中移除 n 个元素,从索引位置 i 开始。但未清理列表的空间。

30、template <typename AT> qsizetype removeAll(const AT &t)

从列表中删除所有与 t 相等的元素。 返回删除的元素数。但未清理列表的空间。

31、void removeAt(qsizetype i)

等同于:remove(i);

32、template <typename Predicate> qsizetype removeIf(Predicate pred)

从列表中删除谓词 pred 为其返回 true 的所有元素。返回删除的元素数(如果有)。(删除返回某条件的元素)

    QList<int> list;
    list << 1<<2<<3<<4<<5<<6<<7<<8<<9;

    list.swapItemsAt(3,5);
    list.removeIf([](const int & value)
    {
        return value > 3;
    });
    qDebug()<<list;

33、template <typename AT> bool removeOne(const AT &t)

从列表中删除与 t 相同的第一个元素。返回元素是否实际上已被删除。

 34、void reserve(qsizetype size)

尝试为至少 size 个元素分配内存。

如果事先知道列表有多大,则应调用此函数以防止重新分配和内存碎片。

reserve() 保留内存但不改变列表的大小。所以应配合调用 resize()。

35、void resize(qsizetype size)

将列表的大小设置为 size。 如果 size 大于当前大小,则将元素添加到末尾;新元素使用默认构造值进行初始化。 如果 size 小于当前大小,则从末尾删除元素。

resize() 不再缩小容量。要摆脱多余的容量,请使用squeeze()。

36、void shrink_to_fit() / void squeeze()

释放任何不需要存储项目的内存。通常很少需要调用此函数。

37、QList<T> sliced(qsizetype pos, qsizetype n)

        QList<T> sliced(qsizetype pos)

返回包含此列表的 n 个元素的子列表,从位置 pos 开始。

38、void swapItemsAt(qsizetype i, qsizetype j) 【实用】

将索引位置 i 的项目与索引位置 j 的项目交换。

39、T takeAt(qsizetype i)

移除索引位置 i 处的元素并返回它。

等同于:

T t = at(i);
remove(i);
return t;

40、QList::value_type takeFirst() / QList::value_type takeLast()

删除列表中的第一项 / 最后一项并返回它。

41、T value(qsizetype i)

返回列表中索引位置 i 处的值。

如果索引 i 超出范围,则该函数返回一个默认构造的值。

如果确定 i 在范围内,可以使用 at() 代替,它返回常引用,稍微快一点。

T value(qsizetype i, QList::parameter_type defaultValue)

如果索引 i 超出范围,则函数返回 defaultValue。


三、相关非成员

1、template <typename T, typename AT> qsizetype erase(QList<T> &list, const AT &t)

从列表列表中删除所有与 t 比较相等的元素。 返回删除的元素数。

注意:与 QList::removeAll() 不同,t 不允许是对列表内元素的引用。如果不能确定,应获取 t 的副本并使用副本调用此函数。

2、template <typename T, typename Predicate> qsizetype erase_if(QList<T> &list, Predicate pred)

用法和 removeIf() 相似。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐