当前位置:首页 >> 开发者生态 >> 【Qt开发流程】之容器类2-使用STL风格迭代器进行遍历,诺基亚6111

【Qt开发流程】之容器类2-使用STL风格迭代器进行遍历,诺基亚6111

cpugpu芯片开发光刻机 开发者生态 1
文件名:【Qt开发流程】之容器类2-使用STL风格迭代器进行遍历,诺基亚6111 【Qt开发流程】之容器类2:使用STL风格迭代器进行遍历 概述

对于每个容器类,都有两种stl风格的迭代器类型:一种提供只读访问,另一种提供读写访问。应该尽可能使用只读迭代器,因为它们比读写迭代器快。 STL迭代器的API以数组中的指针为模型。例如,++操作符将迭代器推进到下一项,*操作符返回迭代器指向的项。实际上,对于QVector和QStack(它们将元素存储在相邻的内存位置),迭代器类型只是T *的一个typedef,而const_iterator类型只是const T *的一个typedef。

示例

在本文档中,将集中讨论QList和QMap。QLinkedList、QVector和QSet的迭代器类型与QList的迭代器具有完全相同的接口;类似地,QHash的迭代器类型与QMap的迭代器具有相同的接口。 下面是按顺序遍历QList<QString>中的所有元素并将它们转换为小写的示例:

QList<QString> list;list << "A" << "B" << "C" << "D";QList<QString>::iterator i;for (i = list.begin(); i != list.end(); ++i)*i = (*i).toLower();

与java风格的迭代器不同,stl风格的迭代器直接指向项。容器的begin()函数返回一个迭代器,该迭代器指向容器中的第一项。容器的end()函数返回一个迭代器,指向容器中最后一项后面一个位置的虚项。End()标记一个无效的位置;它永远不能被取消引用。它通常用于循环的中断条件。如果列表为空,begin()等于end(),因此我们永远不会执行循环。 下图用红色箭头显示了包含四个元素的vector的有效迭代器位置: 使用stl风格的迭代器进行向后迭代可以使用反向迭代器完成:

QList<QString> list;list << "A" << "B" << "C" << "D";QList<QString>::reverse_iterator i;for (i = list.rbegin(); i != list.rend(); ++i)*i = i->toLower();}

在到目前为止的代码片段中,使用一元*操作符检索存储在某个迭代器位置的项(QString类型),然后对其调用QString::toLower()。大多数c++编译器也允许编写i->toLower(),但有些编译器不允许。 对于只读访问,可以使用const_iterator、constBegin()和constEnd()。例如:

QList<QString>::const_iterator i;for (i = list.constBegin(); i != list.constEnd(); ++i)qDebug() << *i; stl风格API

下表总结了stl风格迭代器的API:

方法行为*i返回当前项。++i将迭代器推进到下一项i += n将迭代器向前移动n个元素–i将迭代器向后移动一项i -= n将迭代器向后移动n个元素i - j返回迭代器i和j之间的项数

++和--操作符都可以作为前缀(++i,--i)和后缀(i++,i--)操作符使用。前缀版本修改迭代器并返回对修改后迭代器的引用;后缀版本在修改迭代器之前获取该迭代器的副本,并返回该副本。在忽略返回值的表达式中,我们建议您使用前缀操作符(++i,--i),因为这些操作符略快一些。 对于非常量迭代器类型,一元*操作符的返回值可用于赋值操作符的左侧。 对于QMap和QHash, *操作符返回项的值组件。如果要检索键,请在迭代器上调用key()。为了对称,迭代器类型还提供了一个value()函数来检索值。例如,下面是将QMap中的所有项目打印到控制台:

QMap<int, int> map;...QMap<int, int>::const_iterator i;for (i = map.constBegin(); i != map.constEnd(); ++i)qDebug() << i.key() << ':' << i.value();

由于隐式共享,函数为每个值返回一个容器的成本非常低。Qt API包含几十个函数,每个值返回一个QList或QStringList(例如,QSplitter::sizes())。如果希望使用STL迭代器遍历这些对象,则应该始终获取容器的一个副本,并遍历该副本。例如:

// RIGHTconst QList<int> sizes = splitter->sizes();QList<int>::const_iterator i;for (i = sizes.begin(); i != sizes.end(); ++i)...// WRONGQList<int>::const_iterator i;for (i = splitter->sizes().begin();i != splitter->sizes().end(); ++i)...

对于返回const或非const对容器的引用的函数,不会出现此问题。

隐式共享迭代器问题

隐式共享对于stl风格的迭代器还有另一个后果:当迭代器在容器上处于活动状态时,应该避免复制容器。迭代器指向内部结构,如果复制容器,则应该非常小心地使用迭代器。例句:

QVector<int> a, b;a.resize(100000); // make a big vector filled with 0.QVector<int>::iterator i = a.begin();// WRONG way of using the iterator i:b = a;/*Now we should be careful with iterator i since it will point to shared dataIf we do *i = 4 then we would change the shared instance (both vectors)The behavior differs from STL containers. Avoid doing such things in Qt.*/a[0] = 5;/*Container a is now detached from the shared data,and even though i was an iterator from the container a, it now works as an iterator in b.Here the situation is that (*i) == 0.*/b.clear(); // Now the iterator i is completely invalid.int j = *i; // Undefined behavior!/*The data from b (which i pointed to) is gone.This would be well-defined with STL containers (and (*i) == 5),but with QVector this is likely to crash.*/

上面的例子只显示了QVector的问题,但这个问题存在于所有隐式共享的Qt容器中。

结论

努力奔跑吧,反正没有一片属于你的风景。

协助本站SEO优化一下,谢谢!
关键词不能为空
同类推荐
«    2025年12月    »
1234567
891011121314
15161718192021
22232425262728
293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接