Bootstrap

Qt类 | QList类详解

文章目录

一、QList类介绍

详细内容可参考:https://doc.qt.io/qt-5/qlist.html

  QList是Qt框架中的一种泛型容器类,虽然是以数组列表(array-list)的形式实现的,但是在其前或后添加数据非常块。提供快速的基于索引的访问、插入和删除操作。使用时需要如下设置:

Header:
#include <QList> 
qmake:
QT += core

QList的一些特性如下:

  • 内存布局:QList内部可能以数组或指针数组的形式表示,具体取决于元素类型的大小和是否可移动。“是否可移动”通常指的是元素类型是否支持移动构造函数或移动赋值运算符。

  • 内存分配:QList在内部数组的两端预分配额外空间,以允许列表两端的快速增长。

  • 类型要求:QList的值类型必须是可赋值的

  • 效率:为了效率,QList成员函数在使用前不验证输入,因此调用者应确保参数有效。

  • 兼容性:QList不保证C兼容的数组布局

  • 扩展功能:对于特定类型(如QByteArray和QString),QList提供了额外的成员函数。

二、QList类中的函数

1.构造函数

  QList的构造函数提供了多种初始化QList的方式,包括从迭代器范围、初始化列表、移动构造、复制构造和默认构造。

  • 模板构造函数:

    //InputIterator的值类型必须可以转换为QList的模板参数T
    template <typename InputIterator> 
    QList(InputIterator first, InputIterator last)
    

    使用迭代器范围来构造QList。允许从任何可迭代的容器或数组中初始化QList

    示例:

    std::vector<int> vec = {1, 2, 3, 4, 5};
    QList<int> listFromVec(vec.begin(), vec.end());
    
  • 初始化列表构造函数

    QList(std::initializer_list<T> args)
    

    这个构造函数使用C++11标准引入的初始化列表来构造QList。它接受一个std::initializer_list<T>类型的参数args,其中TQList的元素类型。

    示例:

    QList<int> listFromInitList = {1, 2, 3, 4, 5};
    
  • 移动构造函数

    QList(QList<T> &&other)
    

    移动构造函数会将other所指向的对象的所有权转移给新创建的QList对象,而不是复制对象。使用移动构造函数来避免复制开销。

    示例:

    QList<int> tempList = {1, 2, 3, 4, 5};
    QList<int> movedList = std::move(tempList); // Move semantics
    
  • 复制构造函数

    QList(const QList<T> &other)
    

    使用复制构造函数来创建QList的深拷贝。由于QList的隐式共享特性,这个操作通常是常数时间的。

    隐式共享的理解

    隐式共享是对象的管理办法。一个对象被隐式共享,只是传递该对象的一个指针给使用者,而不实际复制对象数据,只有在使用者修改数据时,才实质复制共享对象给使用者。

    • 共享数据:当复制一个 QList 对象时,新对象不会立即复制原始对象的所有数据。相反,两个对象会共享相同的内部数据(元素数组和内存分配)。它们共享一个指向相同数据的指针。
    • 节省内存:由于两个 QList 对象共享相同的数据,因此复制操作非常快速,并且不会消耗额外的内存,直到需要修改列表之一。
    • 延迟复制:当对共享的 QList 对象进行修改时(例如添加或删除元素),QList 会首先复制共享的数据到一个新的内存区域,然后对新内存区域进行修改。这样,只有当实际需要修改时才会创建数据的副本。
    • 独立操作:一旦数据被复制,两个 QList 对象就会独立操作它们各自的数据副本,后续的修改不会影响另一个对象。

    示例:

    QList<int> list1;
    list1.append(1);
    list1.append(2);
    
    QList<int> list2 = list1; // 快速复制,共享数据
    
    list2.append(3); // 此时 list2 触发数据复制,不再与 list1 共享数据
    

    通过赋值操作创建了 list2,此时 list2list1 共享相同的数据,复制操作很快。当 list2 添加新元素时,触发了数据的复制,list2 现在有自己的数据副本,与 list1 不再共享。

    示例:

    QList<int> originalList = {1, 2, 3, 4, 5};
    QList<int> copiedList = originalList; // Copy constructor
    
  • 默认构造函数

    QList()
    

    创建一个空的QList对象

    示例:

    QList<int> emptyList; // Default constructor
    

2.插入元素的函数

2.1 append函数–在 QList容器的末尾添加元素

  • append函数:在末尾插入元素

    void QList::append(const T &value)    
    
    • 函数作用:

      用于在 QList 容器的末尾添加一个元素,等价于list.insert(size(), value)

    • 示例:

      QList<QString> list;
      list.append("one");
      list.append("two");
      list.append("three");
      // 此时 list 的内容为:["one", "two", "three"]
      
    • 注意事项:

      • 对于非共享的 QList(即没有其他 QList 实例共享其数据),添加元素(如使用 append)通常是快速的,因为 QList 会预先分配额外的内存,以便快速扩展。
      • 如果 QList 是共享的,添加元素时可能会触发数据复制,这可能会稍微慢一些,因为需要先复制数据再进行添加操作。
  • append函数:在末尾插入列表

    void QList::append(const QList<T> &value)
    
    • 函数说明:

      这是一个重载函数。用于将 value 列表中的所有项追加到当前列表中的末尾。

    • 示例:

      QList<int> list1;
      list1.append(1);
      list1.append(2);
      
      QList<int> list2;
      list2.append(3);
      list2.append(4);
      
      list1.append(list2); // 现在 list1 包含 [1, 2, 3, 4]
      
    • 使用场景:

      此函数的使用场景是当你想要合并两个列表时,例如,将一个列表中的所有元素添加到另一个列表的末尾。

2.2 prepend函数–在 QList容器的头部添加元素

void QList::prepend(const T &value)
  • 函数说明:

    用于在 QList 容器的头部添加元素,等价于list.insert(0, value)

  • 示例:

    QList<QString> list;
    list.prepend("one");
    list.prepend("two");
    list.prepend("three");
    // list: ["three", "two", "one"]
    
  • 注意事项:

    • 对于非共享的 QList(即没有其他 QList 实例共享其数据),这个操作是非常高效的。因为 QList 在其内部缓冲区的两侧预先分配了额外的空间,以便在列表的两端快速增长。
    • 如果 QList 是共享的(即有其他 QList 实例共享相同的数据),则在 prepend 操作中可能会触发数据复制,以确保当前列表拥有独立的数据副本。这可能会稍微降低性能,因为需要先复制数据再进行插入操作。

2.3 insert函数–在 QList 容器的指定索引位置插入元素

  • insert函数:特定索引位置

    void QList::insert(int i, const T &value)
    
    • 函数说明:

      用于在 QList 容器的指定索引位置插入元素

      • 如果i == 0,则等价于prepend函数
      • 如果i == size(),则等价于append函数
    • 示例:

      QList<QString> list;
      
      //QList中的operator<<()操作符也可以用于追加元素
      list << "alpha" << "beta" << "delta";
      list.insert(2, "gamma");
      // list: ["alpha", "beta", "gamma", "delta"]
      
    • 注意事项:

      • insert 操作可能会导致列表中的后续元素向后移动,以便为新插入的元素腾出空间。因此,insert 操作的时间复杂度为 O(n),其中 n 是列表中元素的数量。在最坏的情况下,可能需要移动所有现有元素。
      • 如果 QList 是共享的,insert 操作可能会触发数据的复制,以确保当前列表拥有独立的数据副本。这可能会稍微降低性能,因为需要先复制数据再进行插入操作。
  • insert函数:迭代器指向的项

    QList::iterator QList::insert(QList::iterator before, const T &value)
    
    • 函数说明:

      这是一个重载函数。在迭代器 before 指向的项前面插入值。返回一个指向插入项的迭代器。

    • 示例:

      QList<int> list;
      list << 1 << 2 << 4; // 初始化列表
      QList<int>::iterator it = list.begin() + 2; // 获取指向元素 '4' 的迭代器
      list.insert(it, 3); // 在索引 2 的位置前插入元素 '3'
      // 现在 list 是 [1, 2, 3, 4]
      
    • 注意事项:

      传递给函数的迭代器在调用后将无效;应该使用返回的迭代器。

      这是因为插入操作可能会改变列表中元素的布局或导致迭代器所指向的位置发生变化。因此,应使用函数返回的迭代器来引用新插入的元素。

      需要注意迭代器的有效期和在容器修改后迭代器的失效问题

2.4 push_back函数–在 QList容器的末尾添加元素

void QList::push_back(const T &value)
  • 函数说明:

    用于在在 QList容器的末尾添加元素。等价于append(value)push_back函数的存在是为了用于与C++标准模板库(STL)保持兼容性

2.5 push_front函数–在 QList容器的头部添加元素

void QList::push_front(const T &value)
  • 函数说明:

    用于在QList容器的头部添加元素。等价于prepend(value)函数。与push_back类似,push_front也是为了与STL的接口保持一致。

3.删除元素的函数

3.1 removeAt函数–从 QList 容器中移除指定索引 i 处的元素

void QList::removeAt(int i)
  • 函数说明:

    用于从 QList 容器中移除指定索引 i 处的元素。

    调用此函数时,必须确保 i 是一个有效的索引,即它在列表的有效范围内(0 <= i < size())。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    list.removeAt(2); // 移除索引为 2 的元素,即 '3'
    // 现在 list 是 [1, 2, 4, 5]
    
  • 注意事项:

    • 如果索引 i 超出了有效范围(小于 0 或大于或等于 size()),则 removeAt 函数将不会执行任何操作,并且可能触发断言以指示错误。

      如:QList::removeAt(): Index out of range.

    • 此函数不返回任何值,它直接在列表上进行原地修改(in-place modification)。

    • removeAt 操作可能会导致列表中的后续元素向前移动,以填补被移除元素的位置。因此,removeAt 的时间复杂度为 O(n)

3.2 removeFirst函数–从 QList 容器中移除第一个元素

void QList::removeFirst()
  • 函数说明:

    用于移除 QList 容器中的第一个元素。等价于removeAt(0)

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    if (!list.isEmpty()) {
        list.removeFirst(); // 移除第一个元素,即 '1'
        // 现在 list 是 [2, 3, 4, 5]
    }
    
  • 注意事项:

    在调用 removeFirst 之前,需要确保列表不为空。如果列表为空,调用 removeFirst 将不执行任何操作,并且可能会触发断言错误。可以通过先调用 isEmpty() 来检查列表是否为空,从而避免在空列表上调用 removeFirst 导致的问题。

3.3 removeLast函数–从 QList 容器中移除最后一个元素

void QList::removeLast()
  • 函数说明:

    用于从 QList 容器中移除最后一个元素,等价于removeAt(size() - 1)

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    if (!list.isEmpty()) {
        list.removeLast(); // 移除最后一个元素,即 '5'
        // 现在 list 是 [1, 2, 3, 4]
    }
    
  • 注意事项:

    在调用 removeLast 之前,需要确保列表不为空。如果列表为空,调用 removeLast 将不执行任何操作,并且可能会触发断言错误。可以通过先调用 isEmpty() 来检查列表是否为空,从而避免在空列表上调用 removeLast 导致的问题。

3.4 removeOne函数–从 QList 容器中移除第一次出现的指定值 value

bool QList::removeOne(const T &value)
  • 函数说明:

    用于从 QList 容器中移除第一次出现的指定值 value。如果找到该值并成功移除,则函数返回 true;如果列表中没有该值,则不执行任何操作,并返回 false

  • 示例:

    QList<QString> list;
    list << "sun" << "cloud" << "sun" << "rain";
    
    bool isRemoved = list.removeOne("sun"); // 尝试移除列表中的第一个 "sun"
    // list: ["cloud", "sun", "rain"]
    if (isRemoved) {
        qDebug() << "One 'sun' was removed.";
    } else {
        qDebug() << "There was no 'sun' to remove.";
    }
    
  • 注意事项:

    • removeOne 函数只移除第一个匹配的元素,不会影响列表中其他相同的元素。
    • 此函数要求类型 T 重载了 operator==(),以便能够比较列表中的元素与给定的值 value 是否相等。

3.5 removeAll函数–从 QList 容器中移除所有与给定值 value 匹配的元素,并返回被移除元素的数量

int QList::removeAll(const T &value)
  • 函数说明:

    用于从 QList 容器中移除所有与给定值 value 匹配的元素,并返回被移除元素的数量。

  • 示例:

    QList<QString> list;
    list << "sun" << "cloud" << "sun" << "rain";
    list.removeAll("sun");
    // list: ["cloud", "rain"]
    
  • 注意事项:

    • removeAll 函数与 removeOne 函数不同,removeOne 只移除第一个匹配的元素,而 removeAll 移除所有匹配的元素。
    • 此函数要求类型 T 必须重载了 operator==(),以便能够比较列表中的元素与给定的值 value 是否相等。

3.6 takeAt函数–从 QList 容器中移除指定索引 i 处的元素,并返回被移除的元素的值

T QList::takeAt(int i)
  • 函数说明:

    用于从 QList 容器中移除指定索引 i 处的元素,并返回被移除的元素的值。调用此函数时,必须确保 i 是一个有效的索引,即它在列表的有效范围内(即,0 <= i < size())。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    int removedValue = list.takeAt(2); // 移除并获取索引为 2 的元素,即 '3'
    // 现在 list 是 [1, 2, 4, 5]
    // removedValue 是 3
    
  • 注意事项:

    • 如果移除元素后不需要其值,使用 removeAt() 可能更有效率,因为 takeAt 需要处理返回值,这可能涉及额外的开销。然而,如果需要使用被移除的元素的值,takeAt 提供了一个方便的方式来同时完成移除和获取操作。
    • takeAt 操作可能会导致列表中的后续元素向前移动,以填补被移除元素的位置。因此,takeAt 的时间复杂度为 `O(n)

3.7 takeFirst函数–从 QList 容器中移除第一个元素,并返回被移除元素的值

T QList::takeFirst()
  • 函数说明:

    用于从 QList 容器中移除第一个元素,并返回被移除元素的值。等价于takeAt(0)

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    if (!list.isEmpty()) {
        int firstValue = list.takeFirst(); // 移除并获取第一个元素,即 1
        // 现在 list 是 [2, 3, 4, 5]
        // firstValue 是 1
    }
    
  • 注意事项:

    • 调用 takeFirst 之前,应确保列表不为空。如果列表可能为空,应先调用 isEmpty() 函数进行检查,以避免调用 takeFirst 时出现错误
    • 如果不需要使用被移除元素的返回值,使用 removeFirst() 可能更有效率

3.8 takeLast函数–从 QList 容器中移除最后一个元素,并返回被移除元素的值

T QList::takeLast()
  • 函数说明:

    用于从 QList 容器中移除最后一个元素,并返回被移除元素的值。等价于takeAt(size() - 1)

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    if (!list.isEmpty()) {
        int lastValue = list.takeLast(); // 移除并获取最后一个元素,即 5
        // 现在 list 是 [1, 2, 3, 4]
        // lastValue 是 5
    }
    
  • 注意事项:

    • 在调用 takeLast 之前,需要确保列表不为空。如果列表可能为空,应先调用 isEmpty() 函数进行检查,以避免调用 takeLast 时出现错误。
    • 如果不需要使用被移除元素的返回值,使用 removeLast() 可能更有效率

3.9 clear函数–清空 QList 容器中的所有元素

void QList::clear()
  • 函数说明:

    用于清空 QList 容器中的所有元素。调用此函数后,列表将变为空,不再包含任何元素。这个函数不返回任何值,它只对列表本身进行修改。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    list.clear(); // 清空列表
    // 现在 list 是空的
    
  • 注意事项:

    • clear 操作通常需要常数时间 O(1),因为它只涉及重置列表的内部状态,而不需要逐个移除列表中的元素。
    • 如果列表是通过隐式共享机制复制的,clear 操作将只影响当前列表实例,而不会影响其他共享同一数据的列表实例。

3.10 pop_back函数–从 QList 容器中移除最后一个元素

void QList::pop_back()
  • 函数说明:

    用于从 QList 容器中移除最后一个元素,等价于removeLast()函数。pop_back函数是为了与STL容器的接口保持一致

3.11 pop_front函数–从 QList 容器中移除第一个元素

void QList::pop_front()
  • 函数说明:

    用于从 QList 容器中移除第一个元素,等价于removeFirst()函数。与pop_back类似,pop_front也是为了与STL的接口保持一致。

4.访问元素的函数

4.1 at函数–访问 QList 容器中指定索引 i 处的元素,返回对该元素的常量引用

const T &QList::at(int i) const
  • 函数说明:

    用于访问 QList 容器中指定索引 i 处的元素,并返回对该元素的引用。调用此函数时,必须确保 i 是一个有效的索引,即它在列表的有效范围内(i.e., 0 <= i < size())

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    int index = 2;
    int value = list.at(index); // 获取索引为 2 的元素,即 '3'
    // value 是 3
    
  • 注意事项:

    • at 函数提供常数时间复杂度 O(1) 的访问,因为它直接通过索引访问元素,不需要搜索或其他操作。

    • 如果索引 i 超出有效范围,则会发生如下错误

      image-20240714212525380

      最好在使用 at 函数之前,通过 size 成员函数或迭代器来验证索引是否在有效范围内。

    • at 函数返回的是一个对元素的常量引用,这意味着可以通过这个引用来读取元素的值,但在使用 at 时不能直接通过返回值修改列表中的元素。如果需要修改元素,应使用 operator[] 或直接通过迭代器访问。

4.2 value函数–访问 QList 容器中指定索引 i 处的元素的值

  • value函数:未提供越界的默认值

    T QList::value(int i) const
    
    • 函数说明:

      用于访问 QList 容器中指定索引 i 处的元素的值。如果索引 i 超出范围,函数使用类型 T 的默认构造函数创建的对象实例。如果确定索引将在范围内,可以使用 at() 代替,后者稍微快一些。

      使用类型 T 的默认构造函数创建的对象实例:对于内置类型,如 int,这通常意味着返回 0

    • 示例:

      QList<int> list = {1, 2, 3, 4, 5};
      int index = 5; // 索引超出范围
      int value = list.value(index); // 返回默认值 0,因为索引 5 超出列表范围
      // value 是 0
      
    • 注意事项:

      如果可以保证索引始终有效,使用 atoperator[] 可以提供更好的性能。

  • value函数:提供越界的默认值

    T QList::value(int i, const T &defaultValue) const
    
    • 函数说明:

      当索引 i 在列表的有效范围内时,此函数的行为与未重载的 value(int i) 函数相同,即返回列表中索引 i 处的元素值。如果索引 i 超出列表的当前大小,即不在有效范围内,返回提供的 defaultValue

    • 示例:

      QList<int> list = {1, 2, 3, 4, 5};
      int index = 10; // 索引超出范围
      int defaultValue = -1; // 指定默认值
      int value = list.value(index, defaultValue); // 返回 defaultValue,因为索引 10 超出范围
      // value 是 -1
      

4.3 operator[]函数–通过下标访问 QList 容器中的元素,返回该元素的引用

T &QList::operator[](int i)
  • 函数说明:

    QList::operator[]QList 类的一个成员函数,它重载了中括号 [] 运算符,以便通过下标访问列表中的元素。与 at() 函数不同,operator[] 返回的是元素的引用,这意味着可以通过这个引用来修改列表中的元素

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    int index = 2;
    list[index] = 10; // 将索引为 2 的元素修改为 '10'
    // 现在 list 是 [1, 2, 10, 4, 5]
    
  • 注意事项:

    • 使用 operator[] 可以方便地通过下标修改列表中的元素,适用于需要直接访问和修改列表内容的场景。如果不需要修改列表,应该使用 at() 函数。
    • operator[] 函数的运行时间通常是常数时间 O(1),因为它直接通过索引访问元素。然而,如果因为共享而触发了副本操作,这将增加额外的时间开销。
    • 如果 QList 是共享的(即有其他 QList 实例共享相同的数据),调用 operator[] 将触发一个副本操作,使得当前列表拥有独立的数据副本,以确保修改不会影响其他共享该数据的列表实例。
const T &QList::operator[](int i) const
  • 函数说明:

    这个重载版本返回的是元素的常量引用。不能修改列表内容,适合只读访问。

4.4 first函数–获取 QList 容器中第一个元素的引用

T &QList::first()
  • 函数说明:

    用于获取 QList 容器中第一个元素的引用。调用此函数时,必须确保列表不为空

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    if (!list.isEmpty()) {
        int firstItem = list.first(); // 获取第一个元素,即 '1'
        // firstItem 是 1
    }
    
  • 注意事项:

    • 如果需要处理可能为空的列表,应在调用 first 之前使用 isEmpty() 函数进行检查,以避免运行时错误
    • 如果只需要读取第一个元素的值,可以使用 constFirst() 函数。如果需要修改列表的第一个元素,可以使用first 函数。
const T &QList::first() const
const T &QList::constFirst() const
  • 函数说明:

    用于获取 QList 容器中第一个元素的常量引用。这意味着你可以读取这个元素的值,但不能修改它。适用于只读场景或在常量列表上操作。

4.5 front函数–获取 QList 容器中第一个元素的引用

T &QList::front()
const T &QList::front() const
  • 函数说明:

    用于访问列表的第一个元素。等价于first()函数。提供此函数是为了与STL容器的接口保持一致

4.6 last函数–获取 QList 容器中最后一个元素的引用

T &QList::last()
  • 函数说明:

    用于获取 QList 容器中最后一个元素的引用。这意味着你可以读取这个元素的值,并且可以修改它。调用 last 之前,需要确保列表不为空。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    if (!list.isEmpty()) {
        int lastItem = list.last(); // 获取最后一个元素,即 5
        // lastItem 是 5
    }
    
  • 注意事项:

    • 如果列表可能为空,应先调用 isEmpty() 函数进行检查
    • 如果只需要读取最后一个元素的值,可以使用 constLast() 函数。如果需要修改列表的最后一个元素,可以使用 last() 函数。
const T &QList::last() const
const T &QList::constLast() const
  • 函数说明

    用于获取 QList 容器中第一个元素的常量引用。这意味着你可以读取这个元素的值,但不能修改它。适用于只读场景或在常量列表上操作。

4.7 back函数–获取 QList 容器中最后一个元素的引用

T &QList::back()
const T &QList::back() const
  • 函数说明:

    back函数用于获取对QList容器最后一个元素的引用。等价与last()函数。提供此函数是为了与STL容器的接口保持一致。

4.8 mid函数–从QList对象中提取一个子列表

QList<T> QList::mid(int pos, int length = -1) const
  • 函数说明:

    用于从QList对象中提取一个子列表,子列表的起始位置由pos指定。如果length为-1(默认值),则从pos开始包括所有元素;否则包括length个元素(或者如果有不足length个剩余元素,则包括所有剩余元素)。

  • 示例:

    QList<int> list = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    // 获取从索引3开始的子列表,包括所有剩余元素
    QList<int> subList1 = list.mid(3);    //SubList1: 3 4 5 6 7 8 9 
    // 获取从索引3开始的子列表,长度为4
    QList<int> subList2 = list.mid(3, 4); //SubList2: 3 4 5 6 
    
  • 注意事项:

    mid函数通常是一个高效的操作,因为它可能只需要复制指定范围内的元素引用,而不是复制整个列表。

5.查找元素的函数

5.1 contains函数–检查 QList 容器中是否存在给定值 value 的至少一个匹配项

bool QList::contains(const T &value) const
  • 函数说明:

    用于检查 QList 容器中是否存在给定值 value 的至少一个匹配项。如果列表中至少存在一个元素与 value 相等,则函数返回 true。如果没有找到匹配项,则返回 false

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    bool containsThree = list.contains(3); // 返回 true
    bool containsSix = list.contains(6); // 返回 false
    
  • 注意事项:

    • 此函数要求元素类型 T 必须重载了 operator==(),以便能够比较元素是否相等。因为 contains 需要遍历列表并比较每个元素与给定值。
    • 使用 contains 函数可以方便地检查列表中是否存在某个元素,而不需要手动遍历列表。

5.2 indexof函数–查找特定值 value 在 QList 容器中的索引位置并返回

int QList::indexOf(const T &value, int from = 0) const
  • 函数说明:

    用于查找特定值 valueQList 容器中的索引位置。搜索从指定的索引位置 from 开始,如果不提供 from 参数,默认从列表开头(索引 0)开始。如果在列表中找到该值,函数返回它首次出现的索引;如果没有找到,返回 -1

  • 示例:

    QList<QString> list;
    list << "A" << "B" << "C" << "B" << "A";
    list.indexOf("B");          // 返回 1
    list.indexOf("B", 1);       // 返回 1
    list.indexOf("B", 2);       // 返回 3
    list.indexOf("X");          // 返回 -1
    
  • 注意事项:

    • 此函数要求元素类型 T 必须重载了 operator==(),以便能够比较元素是否相等。
    • indexOf 函数在列表中从指定的 from 索引开始线性搜索,直到找到匹配的元素或到达列表末尾。

5.3 lastIndexOf函数–在 QList 容器中查找特定值 value 的索引位置

int QList::lastIndexOf(const T &value, int from = -1) const
  • 函数说明:

    用于在 QList 容器中查找特定值 value 的索引位置,不过这次是从后向前搜索。搜索从指定的索引位置 from 开始,如果不提供 from 参数,默认从列表末尾(索引 -1)开始。如果在列表中找到该值,函数返回它最后一次出现的索引;如果没有找到,返回 -1

  • 示例:

    QList<QString> list;
    list << "A" << "B" << "C" << "B" << "A";
    list.lastIndexOf("B");      // 返回 3
    list.lastIndexOf("B", 3);   // 返回 3
    list.lastIndexOf("B", 2);   // 返回 1
    list.lastIndexOf("X");      // 返回 -1
    
  • 注意事项:

    • 此函数要求元素类型 T 必须重载了 operator==()
    • lastIndexOf 函数在列表中从指定的 from 索引开始反向搜索,直到找到匹配的元素或到达列表开头。

5.4 startsWith函数–检查 QList 对象的第一个元素是否与给定的值 value 相等

bool QList::startsWith(const T &value) const
  • 函数说明:

    用于检查QList对象的第一个元素是否与给定的值value相等。如果相等,则返回true;否则返回false

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    
    // 检查列表的第一个元素是否为特定的值
    if (list.startsWith(1)) {
        std::cout << "The list starts with the value 1." << std::endl;
    } else {
        std::cout << "The list does not start with the value 1." << std::endl;
    }
    
  • 注意事项:

    • 这是一个常量成员函数,意味着它不会修改QList对象的状态。

5.5 endsWith函数–检查QList对象的最后一个元素是否与给定的值value相等

bool QList::endsWith(const T &value) const
  • 函数说明:

    用来检查QList对象的最后一个元素是否与给定的值value相等。如果相等则返回true;否则返回false

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    
    // 检查列表的最后一个元素是否为特定的值
    if (list.endsWith(5)) {
        std::cout << "The list ends with the value 5." << std::endl;
    } else {
        std::cout << "The list does not end with the value 5." << std::endl;
    }
    

6.大小与空检查函数

这三个函数的时间复杂度均为O(1)

6.1 count函数–返回 QList 容器中元素的数量

int QList::count() const
  • 函数说明:

    用于返回 QList 容器中元素的数量。等价于size()函数。两者可以互换使用,没有功能上的区别。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    int itemCount = list.count(); // 获取元素数量
    // itemCount 是 5
    
int QList::count(const T &value) const
  • 函数说明:

    用于统计并返回 valueQList 中出现的次数

  • 示例:

    QList<int> list = {1, 2, 2, 2, 5};
    int itemCount = list.count(2); // 获取元素数量
    // itemCount 是 3
    
  • 注意事项:

    • 函数要求值类型具有 operator==() 的实现,即必须能够比较两个 T 类型对象是否相等。

    • 函数是 const 成员函数,意味着它不会修改 QList 对象的状态。

    • 对于基本数据类型(如 intdouble 等)和大多数 Qt 类型,== 操作符默认是可用的。如果使用自定义类型,你需要确保为该类型重载了 == 操作符。

6.2 size函数–返回 QList 容器中元素的数量

int QList::size() const
  • 函数说明:

    用于返回 QList 容器中元素的数量。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    int listSize = list.size(); // 获取列表大小
    // listSize 是 5
    

6.3 length函数–获取列表中元素的数量

int QList::length() const
  • 函数说明:

    用于获取列表中元素的数量。等价于count()函数

6.4 isEmpty函数–检查 QList 容器是否为空

bool QList::isEmpty() const
  • 函数说明:

    用于检查 QList 容器是否为空,即列表中是否没有任何元素。当列表中没有元素时,此函数返回 true;如果列表中至少有一个元素,函数返回 false

  • 示例:

    QList<int> list;
    if (list.isEmpty()) {
        qDebug() << "The list is empty.";
    } else {
        qDebug() << "The list is not empty.";
    }
    
  • 使用场景:

    isEmpty 函数通常用于在执行操作之前验证列表是否包含元素

7.其他操作函数–替换、交换、移动、预留空间

7.1 replace函数–将 QList 中指定索引 i 处的元素替换为新的值value

void QList::replace(int i, const T &value)
  • 函数说明:

    用于将QList中指定索引i处的元素替换为新的值value。需要确保提供的索引i是有效的。这意味着索引i必须在列表的当前大小范围内(即,0 <= i < size())。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    
    // 替换索引为2的元素(即,元素3)
    list.replace(2, 30);
    //交换后:1 2 30 4 5 
    

7.2 swap函数–交换两个QList对象的元素

void QList::swap(QList<T> &other)
  • 函数说明:

    用于交换两个QList对象的元素。这意味着函数执行后,两个列表将拥有对方的元素。

  • 示例:

    QList<int> list1 = {1, 2, 3};
    QList<int> list2 = {4, 5, 6};
    
    // 交换两个列表的内容
    list1.swap(list2);
    //List1 contains: 4 5 6
    //List2 contains: 1 2 3
    
  • 注意事项:

    • 这个操作的效率高,因为它通常只涉及交换内部指针或引用计数等少量数据,而不是交换实际的元素数据。在Qt中,由于QList的隐式共享机制,交换操作通常只需要交换内部数据的引用,因此非常快速。
    • 由于交换操作不涉及资源分配或复杂的状态转换,它被认为是一个不会失败的操作。这意味着swap函数总是能够成功执行,不会抛出异常或返回错误。

7.3 swapItemsAt函数–交换QList中两个指定索引位置的元素

void QList::swapItemsAt(int i, int j)
  • 函数说明:

    swapItemsAt函数用于交换QList中两个指定索引位置的元素。这是一个就地操作,不涉及元素的移除和重新插入,因此通常比先移除再插入更高效。

  • 示例:

    QList<QString> list;
    list << "A" << "B" << "C" << "D" << "E" << "F";
    list.swapItemsAt(1, 4);
    // 列表:["A", "E", "C", "D", "B", "F"]
    
  • 注意事项:

    • 交换操作通常是非常快速的,因为它只涉及几个指针或引用的交换,不需要复制或移动元素数据。
    • swapItemsAt函数从Qt 5.13版本开始提供

7.4 move函数–将 QList 中一个位置的元素移动到另一个位置

void QList::move(int from, int to)
  • 函数说明:

    将位于索引位置from的项移动到索引位置to。这不会改变元素的值,只是改变其在列表中的位置。等价于insert(to, takeAt(from))

  • 示例:

    QList<QString> list;
    list << "A" << "B" << "C" << "D" << "E" << "F";
    list.move(1, 4);
    // 列表:["A", "C", "D", "E", "B", "F"]
    
  • 注意事项:

    • 如果to大于from,剪切的元素将插入到to之后的所有元素之前;如果to小于from,剪切的元素将插入到to之前。
    • move操作通常比删除一个元素然后插入一个新元素更高效,因为它避免了复制整个列表的开销。

7.5 reserve函数–预留alloc个元素的空间

void QList::reserve(int alloc)
  • 函数说明:

    用于为QList预留足够的内存空间以存储指定数量的元素。这有助于提高性能,尤其是在你知道将要添加大量元素的情况下。

  • 示例:

    QList<int> list;
    // 预测将添加100个元素,预先分配空间
    list.reserve(100);
    
  • 注意事项:

    • 使用场景:当你预计会向QList中添加大量元素时,可以在添加之前调用reserve,以优化性能。例如,在读取大量数据并将其添加到列表中之前,可以先调用reserve
    • 性能优化:通过预留空间,可以减少在添加元素时可能发生的多次内存重新分配,从而提高性能。这对于大型数据集或在循环中频繁添加元素的场景特别有用。
    • 如果指定的alloc值小于列表当前的元素数量,reserve函数将不执行任何操作,因为当前的内存分配已经足够存储现有元素。

8.转换成其他容器类

8.1 toSet函数–将QList对象转换为QSet对象

QSet<T> QList::toSet() const
  • 函数说明:

    toSet函数将QList对象转换为QSet对象。由于QSet是一个不允许重复元素的集合,转换后的QSet可能包含比原始列表更少的元素,因为所有重复项都会被去除。

    此函数适用于需要去除列表中的重复项并创建一个唯一元素集合的场景。

  • 示例:

    QStringList list;
    list << "Julia" << "Mike" << "Mike" << "Julia" << "Julia";
    
    QSet<QString> set = list.toSet();
    set.contains("Julia");  // 返回 true
    set.contains("Mike");   // 返回 true
    set.size();             // 返回 2
    

8.2 toVector函数–将QList对象转换为QVector对象

QVector<T> QList::toVector() const
  • 函数说明:

    toVector函数将QList对象转换为QVector对象。转换后的QVector包含与QList相同的元素序列。

  • 示例:

    QStringList list;
    list << "Sven" << "Kim" << "Ola";
    
    QVector<QString> vect = list.toVector();
    // vect: ["Sven", "Kim", "Ola"]
    
  • 注意事项:

    • 此函数适用于需要将列表数据转换为向量数据结构的场景。QVector提供了不同于QList的特性,例如可能更好的缓存局部性和固定内存大小。
    • 从Qt 5.14开始,推荐使用范围构造函数来直接从列表创建QVector,这可能比使用toVector方法更直接和高效。

8.3 toStdList函数

std::list<T> QList::toStdList() const
  • 函数说明:

    toStdList函数将QList对象转换为C++标准模板库中的std::list对象。转换后的std::list包含与QList相同的元素序列。

  • 示例:

    QList<double> list;
    list << 1.2 << 0.5 << 3.14;
    
    std::list<double> stdlist = list.toStdList();
    
  • 注意事项:

    • 此函数用于在Qt容器和标准库容器之间迁移数据。std::list是一个链表,提供不同于QList的特性,例如在列表中间插入和删除元素的高效操作。
    • 从Qt 5.14开始,推荐使用范围构造函数来直接从QList创建std::list,这可能比使用toStdList方法更直接和高效。

9.迭代器相关函数

9.1 begin、cbegin、rbegin、crbegin、constBegin函数

QList::iterator QList::begin()
  • 函数说明:

    begin函数提供了对QList容器开始位置的访问,返回的迭代器可以用于遍历列表中的元素。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    
    // 使用begin()和end()迭代器遍历列表
    for (QList<int>::iterator it = list.begin(); it != list.end(); ++it) {
        std::cout << *it << " ";
    }
    
  • 注意事项:

    返回的迭代器是STL(标准模板库)风格的,这意味着它与C++ STL算法兼容,可以使用这些算法对QList进行操作。

QList::const_iterator QList::begin() const
  • 函数说明:

    这个重载的begin函数返回一个指向QList容器中第一个元素的常量迭代器。与非const版本的begin函数返回一个可修改的迭代器不同,这个版本的begin函数返回的迭代器不允许修改元素的值。它只能用于读取元素。

QList::const_iterator QList::cbegin() const
  • 函数说明:

    cbegin函数提供了对QList容器开始位置的只读访问,返回的迭代器可以用于遍历列表中的元素,但不允许修改这些元素。返回的迭代器是STL风格的。

QList::reverse_iterator QList::rbegin()
  • 函数说明:

    rbegin函数提供了对QList容器进行逆序遍历的能力,返回的逆向迭代器指向按逆序排列的第一个元素,即最后一个元素

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    
    // 使用rbegin()和rend()迭代器逆序遍历列表
    for (QList<int>::reverse_iterator it = list.rbegin(); it != list.rend(); ++it) {
        std::cout << *it << " ";
    }
    
  • 注意事项:

    返回的逆向迭代器遵循STL的迭代器规范,允许使用STL算法对容器进行逆序迭代。

QList::const_reverse_iterator QList::rbegin() const
  • 函数说明:

    这个重载的rbegin函数提供了对QList容器进行只读逆序遍历的能力,返回的逆向迭代器可以用于逆序读取列表中的元素。

QList::const_reverse_iterator QList::crbegin() const
  • 函数说明:

    crbegin函数提供了对QList容器进行只读逆序遍历的能力。返回的逆向迭代器指向按逆序排列的第一个元素,即原本的最后一个元素。返回的逆向迭代器遵循STL的迭代器规范,允许使用STL算法对容器进行只读的逆序迭代。

  • 示例:

    const QList<int> list = {1, 2, 3, 4, 5};
    
    // 使用crbegin()和crend()迭代器进行只读逆序遍历
    for (QList<int>::const_reverse_iterator it = list.crbegin(); it != list.crend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    
QList::const_iterator QList::constBegin() const
  • 函数说明:

    constBegin函数提供了对QList容器第一个元素的只读访问。返回的迭代器可以用于遍历列表中的元素,但不能修改元素的值。返回的迭代器是STL风格的,可以与C++ STL算法一起使用,进行只读迭代。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    
    // 使用constBegin()和constEnd()进行只读遍历
    for (QList<int>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it) {
        std::cout << *it << " ";
    }
    

9.2 end、cend、rend、crend、constEnd函数

QList::iterator QList::end()
  • 函数说明:

    end函数返回一个迭代器,它指向QList容器末尾的虚构位置(指向末尾之后的迭代器),即最后一个元素之后的位置。这个迭代器并不代表一个实际的元素,而是作为遍历容器的结束条件。

  • 使用场景:

    此函数通常与begin函数配合使用,用于在循环中遍历容器的所有元素。end提供的迭代器用作循环的退出条件,确保不会访问到容器之外的内存。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5};
    
    // 使用begin()和end()迭代器遍历列表
    QList<int>::iterator it;
    for (it = list.begin(); it != list.end(); ++it) {
        std::cout << *it << " ";
    }
    
  • 注意事项:

    由于end返回的是指向末尾之后的迭代器,解引用这个迭代器是未定义行为。因此,它应当只用于比较操作,判断迭代器是否已经遍历完容器的所有元素。

QList::const_iterator QList::end() const
  • 函数说明:

    与非const版本的end函数不同,返回的迭代器不允许修改容器中的元素。

QList::const_iterator QList::cend() const
  • 函数说明:

    cend函数提供了对QList容器末尾之后虚构位置的只读访问。返回的只读迭代器可以用于逆序遍历或作为遍历结束的条件。

QList::reverse_iterator QList::rend()
  • 函数说明:

    rend函数返回一个逆向迭代器,它指向QList容器在逆序遍历时的结束位置之后。此函数通常与rbegin函数配合使用,用于在循环中逆序遍历容器的所有元素。rend提供的迭代器用作逆序循环的退出条件。

  • 注意事项:

    rend返回的迭代器指向结束位置之后,因此不能解引用。它仅用于比较操作,以判断迭代器是否已经逆序遍历完容器的所有元素。

QList::const_reverse_iterator QList::rend() const
  • 函数说明:

    返回的迭代器是常量迭代器,因此只能用来读取元素,不能用来修改元素。这在需要避免修改容器内容的只读逆序遍历中非常有用。

QList::const_reverse_iterator QList::crend() const
  • 函数说明:

    rend函数返回的可修改迭代器不同,crend返回的迭代器是常量的,意味着它不能用于修改容器中的元素,只能用于读取。此函数通常与crbegin函数配合使用,用于在循环中以只读方式逆序遍历容器的所有元素。crend提供的迭代器用作逆序循环的退出条件。

QList::const_iterator QList::constEnd() const
  • 函数说明:

    constEnd函数提供了对QList容器末尾之后虚构位置的只读访问。返回的迭代器是常量的,意味着它不能用于修改容器中的元素,只能用于遍历到容器的结束。

9.3 erase函数–移除与迭代器向关联的项

QList::iterator QList::erase(QList::iterator pos)
  • 函数说明:

    从列表中移除与迭代器pos关联的项,并返回返回一个迭代器,指向移除元素之后(可能是end())。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5, 6};
    
    // 移除索引为2的元素(即值为3的元素)
    QList<int>::iterator it = list.begin() + 2;
    it = list.erase(it);
    //1 2 4 5 6 
    
  • 注意事项:

    使用erase函数后,原先迭代器pos所指向的元素将不再存在,迭代器也会失效。返回的迭代器可用于继续遍历或删除操作。

QList::iterator QList::erase(QList::iterator begin, QList::iterator end)
  • 函数说明:

    这个重载的erase函数用于移除QList中指定迭代器范围内的所有元素。返回一个迭代器,指向end在调用之前所引用的那个元素。

  • 示例:

    QList<int> list = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    // 移除从索引1开始到索引4结束的元素(不包括索引4)
    QList<int>::iterator newEnd = list.erase(list.begin() + 1, list.begin() + 4);
    
  • 注意事项:

    使用erase函数后,从beginend(不包括end)的所有迭代器都会失效,因为它们所指向的元素已经被删除。返回的迭代器可用于继续遍历或删除操作。

10.QList支持的操作符函数

  • operator=

    QList<T> &QList::operator=(QList<T> &&other)
    QList<T> &QList::operator=(const QList<T> &other)
    
  • operator!=

    bool QList::operator!=(const QList<T> &other) const
    
  • operator+

    QList<T> QList::operator+(const QList<T> &other) const
    
  • operator+=

    QList<T> &QList::operator+=(const QList<T> &other)
    
  • operator<<

    QList<T> &QList::operator<<(const QList<T> &other)
    QList<T> &QList::operator<<(const T &value)
    
    //Writes the list list to stream out
    template <typename T> QDataStream &operator<<(QDataStream &out, const QList<T> &list)
    
  • operator==

    bool QList::operator==(const QList<T> &other) const
    
  • operator[]

    T &QList::operator[](int i)
    const T &QList::operator[](int i) const
    
  • operator<

    template <typename T> bool operator<(const QList<T> &lhs, const QList<T> &rhs)
    
  • operator<=

    template <typename T> bool operator<=(const QList<T> &lhs, const QList<T> &rhs)
    
  • operator>

    template <typename T> bool operator>(const QList<T> &lhs, const QList<T> &rhs)
    
  • operator>=

    template <typename T> bool operator>=(const QList<T> &lhs, const QList<T> &rhs)
    
  • operator>>

    //Reads a list from stream in into list.
    template <typename T> QDataStream &operator>>(QDataStream &in, QList<T> &list)
    
;