Qt中的通用模板算法QtAlgorithms(qDeleteAll,qBinaryFind,qCountLeadingZeroBits,qPopulationCount,qFill,qSwap,qSort)

时间:2021-07-29 23:43:43

Qt在<QtAlgorithms>头文件中为我们提供了一系列的全局模板方法,这些模板方法主要用于容器操作,比如qDeleteAll()。其在Qt中的声明如下:

void qDeleteAll(ForwardIterator begin, ForwardIterator end)
void qDeleteAll(const Container &c)
        该方法接受一个容器或由两个迭代器确定的容器区间,其作用是对容器中的每一个元素调用operator delete释放元素所占用的空间。所以,作为参数传递的容器中的元素必须是non-const 指针类型,不能是基本数据类型。同时,这些算法能用于任何具有STL风格迭代器的容器,包括QList,QLinkedList,QVector, QMap,QHash等。注意,qDeleteAll() 只是释放容器中每个指针元素所占用的空间,并不会清空容器或容器区间。比如,

QList<Employee *> list;
list.append(new Employee("Blackpool", "Stephen"));
list.append(new Employee("Twist", "Oliver"));

qDeleteAll(list.begin(), list.end());
list.clear();
像上面的例子所示,如果我们想清空容器,必须手动调用一下容器的相关成员函数。另一方面,当qDeleteAll() 应用于关联容器时,如QMap,QHash等,这些容器中往往存放的都是key-value对,但qDeleteAll() 只能释放value所对应的内存空间,而不能释放key所对应的内存空间。
        大部分方法都和上面一样接受STL风格的迭代器作为参数,并且由于这些方法是通用方法,不依赖具体的迭代器类,所以可以将任何满足条件的迭代器作为参数传入。当然,迭代器的类型要和方法的需求一致,比如qFill() 方法接受两个forward iterator,就必须传递两个前向迭代器进去,否则会引发编译错误。并且我们知道在STL中,任何行为像迭代器的东西就是迭代器。对于Qt来说也是一样,所以,这些方法不仅仅能应用于标准的Qt容器和STL容器,也可以应用于普通的数组和指针。比如,下面的例子,对于name_table数组中的每一个HTML实体,在value_table中查找该实体所对应的Unicode编码。因为name_table 是按字母排序的,所以此处可以使用qBinaryFind() 进行二分查找。

QChar resolveEntity(const QString &entity)
{
static const QLatin1String name_table[] = { "AElig", "Aacute", ..., "zwnj"};
static const ushort value_table[] = {0x0061, 0x00c1, ..., 0x200c};
int N = sizeof(name_table) / sizeof(name_table[0]);
const QLatin1String *name = qBinaryFind(name_table, name_table + N, entity);
int index = name - name_table;
if (index == N)
return QChar();

return QChar(value_table[index]);
}
 Qt容器所支持的迭代器类型

上面说到这些通用算法主要用于操作容器,而操作容器最常用的方式就是使用迭代器,所以,我们在看一下Qt中所支持的迭代器类型:

输入迭代器

输入迭代器可以用来从一个容器中顺序的读取数据。所以这种迭代器必须提供==和!=运算符来比较两个迭代器是否相等,同时还得有取得每项数据的*运算符和迭代到下一项的++运算符。Qt中容器的迭代器类型都是输入迭代器。

输出迭代器

输出迭代器用来想容器中顺序的写入数据。其操作和上面的输入迭代器大同小异。其也提供了用于存取数据的*运算符和迭代到下一项的++运算符。Qt容器的non-const 迭代器都是输入迭代器。

前向迭代器

前向迭代器其实就是 既满足输入迭代器的要求又满足输出迭代器的要求的一种迭代器。Qt容器的所有non-const容器都是前向迭代器。

双向迭代器

双向迭代器除了满足前向迭代器的要求外,还提供了--运算符以实现向后迭代的功能。Qt容器的non-const迭代器都是双向迭代器。

随机存取迭代器

随机存取迭代器是最后一种,也是功能最强大的一种迭代器,它不仅支持双向迭代器的操作,还支持以下各种操作:

i += n 将迭代器想前步进n位
i -= n 将迭代器向后步进n位
i +n or n + i 返回迭代器i前面n位所对应的迭代器
i - n 返回迭代器i后面n位所对应的迭代器
i - j 返回迭代器i 和 j 之间的元素的个数
i[n] 等价于 *(i + n)
i < j  比较迭代器i是否在迭代器j的后面

Qt中的QList 和 QVector 的non-const 迭代器是随机存取迭代器。
其他通用方法

除了上面的qDeleteAll() 算法,Qt在<QtAlgorithms>头文件里还为我们提供了另外两个通用方法,声明如下:

uint qCountLeadingZeroBits(quint32 v)
uint qCountLeadingZeroBits(quint8 v)
uint qCountLeadingZeroBits(quint16 v)
uint qCountLeadingZeroBits(quint64 v)
uint qCountTrailingZeroBits(quint32 v)
uint qCountTrailingZeroBits(quint8 v)
uint qCountTrailingZeroBits(quint16 v)
uint qCountTrailingZeroBits(quint64 v)
uint qPopulationCount(quint32 v)
uint qPopulationCount(quint8 v)
uint qPopulationCount(quint16 v)
uint qPopulationCount(quint64 v)
qCountLeadingZeroBits() 用于计算一个整数所对应的二进制数中从最高位(MSB)算起有多少个0,比如 qCountLeadingZeroBits(8) 返回28,因为十进制 “8” 所对应的二进制是“1000”,总共32位,所以从最高位算起有28个0。

qCountTrailingZeroBits() 的作用同上,只不过其返回的是从最低有效位(LSB)算起有多少个0。

qPopulationCount() 返回一个整数的二进制表示中 1 的个数。该个数称为 数字的 “汉明权重”。关于“汉明权重”的详细信息可参看*汉明权重。

被废弃的通用方法

除了上面说的三个通用方法,其实Qt还提供了其他的通用方法,比如上面提到过的qBinaryFind()。但由于这些通用方法大多和STL中的标准算法功能重复,所以,从Qt5.0开始,这些就被标记为废弃的函数,而建议大家直接使用STL中的标准算法。Qt5.7中所列的被废弃的算法如下:

RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
Container::const_iterator qBinaryFind(const Container &container, const T &value)
OutputIterator qCopy(InputIterator begin1, InputIterator end1, OutputIterator begin2)
BiIterator2 qCopyBackward(BiIterator1 begin1, BiIterator1 end1, BiIterator2 end2)
void qCount(InputIterator begin, InputIterator end, const T &value, Size &n)
void qCount(const Container &container, const T &value, Size &n)
bool qEqual(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2)
void qFill(ForwardIterator begin, ForwardIterator end, const T &value)
void qFill(Container &container, const T &value)
InputIterator qFind(InputIterator begin, InputIterator end, const T &value)
Container::const_iterator qFind(const Container &container, const T &value)
LessThan qGreater()
LessThan qLess()
RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
Container::const_iterator qLowerBound(const Container &container, const T &value)
void qSort(RandomAccessIterator begin, RandomAccessIterator end)
void qSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
void qSort(Container &container)
void qStableSort(RandomAccessIterator begin, RandomAccessIterator end)
void qStableSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
void qStableSort(Container &container)
void qSwap(T &var1, T &var2)
RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan)
Container::const_iterator qUpperBound(const Container &container, const T &value)

这些函数大都可以见名知意,在此就不详细讲解了。另外,这些函数被标记为废弃,但并未从qt中移除,所以关于每个函数的具体信息,可参看Qt帮助文档。但还是建议不要使用这些被废弃的函数,以免这些函数在将来的某个版本被移除而导致代码的不可移植性。
---------------------
作者:求道玉
来源:CSDN
原文:https://blog.csdn.net/Amnes1a/article/details/60868344
版权声明:本文为博主原创文章,转载请附上博文链接!