首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用for遍历QMap

使用for遍历QMap
EN

Stack Overflow用户
提问于 2011-12-15 17:31:17
回答 9查看 84.8K关注 0票数 60

我有一个QMap对象,我正在尝试将它的内容写入一个文件。

代码语言:javascript
复制
QMap<QString, QString> extensions;
//.. 

for(auto e : extensions)
{
  fout << e.first << "," << e.second << '\n';
}  

为什么我会得到:error: 'class QString' has no member named 'first' nor 'second'

e不是QPair类型吗

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2011-12-16 10:18:34

如果您想使用firstsecond的STL样式,请执行以下操作:

代码语言:javascript
复制
for(auto e : extensions.toStdMap())
{
  fout << e.first << "," << e.second << '\n';
}

如果您想使用Qt提供的功能,请执行以下操作:

代码语言:javascript
复制
for(auto e : extensions.keys())
{
  fout << e << "," << extensions.value(e) << '\n';
}
票数 63
EN

Stack Overflow用户

发布于 2011-12-16 10:51:00

基于范围的C++11 -for使用解引用迭代器的类型作为自动推导的“光标”类型。这里,它是表达式*map.begin()的类型。

由于QMap::iterator::operator*()返回一个对值(类型为QString &)的引用,因此无法使用该方法访问该键。

您应该使用文档中描述的一种迭代器方法,但应避免使用

  • keys(),因为它涉及创建键列表,然后搜索每个键的值;或者,
  • toStdMap(),因为它将所有映射元素复制到另一个映射元素

而这并不是最优的。

您还可以使用包装器将QMap::iterator作为auto类型:

代码语言:javascript
复制
template<class Map>
struct RangeWrapper {
    typedef typename Map::iterator MapIterator;
    Map &map;

    RangeWrapper(Map & map_) : map(map_) {}

    struct iterator {
        MapIterator mapIterator;
        iterator(const MapIterator &mapIterator_): mapIterator(mapIterator_) {}
        MapIterator operator*() {
            return mapIterator;
        }
        iterator & operator++() {
            ++mapIterator;
            return *this;
        }
        bool operator!=(const iterator & other) {
            return this->mapIterator != other.mapIterator;
        }
    };
    iterator begin() {
        return map.begin();
    }
    iterator end() {
        return map.end();
    }
};

// Function to be able to use automatic template type deduction
template<class Map>
RangeWrapper<Map> toRange(Map & map)
{
    return RangeWrapper<Map>(map);
}

// Usage code
QMap<QString, QString> extensions;
...
for(auto e : toRange(extensions)) {
    fout << e.key() << "," << e.value() << '\n';
}

还有另一个包装器here

票数 55
EN

Stack Overflow用户

发布于 2015-07-05 09:34:30

对于对优化感兴趣的人,我尝试了几种方法,做了一些微基准测试,我可以得出结论,风格的方法比快得多。

我尝试过用以下方法添加整数:

  • QMap::values()
  • Java样式迭代器(按照documentation)
  • STL样式迭代器中的建议(也是文档中的建议)

我将它与QList/QVector的整数求和进行了比较

结果:

代码语言:javascript
复制
Reference vector :   244  ms
Reference list :     1239  ms

QMap::values() :     6504  ms
Java style iterator :    6199  ms
STL style iterator :     2343  ms

感兴趣的人的代码:

代码语言:javascript
复制
#include <QDateTime>
#include <QMap>
#include <QVector>
#include <QList>
#include <QDebug>

void testQMap(){
    QMap<int, int> map;
    QVector<int> vec;
    QList<int> list;

    int nbIterations = 100;
    int size = 1000000;
    volatile int sum = 0;

    for(int i = 0; i<size; ++i){
        int randomInt = qrand()%128;
        map[i] = randomInt;
        vec.append(randomInt);
        list.append(randomInt);
    }


    // Rererence vector/list
    qint64 start = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        for(int j : vec){
            sum += j;
        }
    }
    qint64 end = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "Reference vector : \t" << (end-start) << " ms";

    qint64 startList = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        for(int j : list){
            sum += j;
        }
    }
    qint64 endList = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "Reference list : \t" << (endList-startList) << " ms";

    // QMap::values()
    qint64 start0 = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        QList<int> values = map.values();
        for(int k : values){
            sum += k;
        }
    }
    qint64 end0 = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "QMap::values() : \t" << (end0-start0) << " ms";


    // Java style iterator
    qint64 start1 = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        QMapIterator<int, int> it(map);
        while (it.hasNext()) {
            it.next();
            sum += it.value();
        }
    }
    qint64 end1 = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "Java style iterator : \t" << (end1-start1) << " ms";


    // STL style iterator
    qint64 start2 = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        QMap<int, int>::const_iterator it = map.constBegin();
        auto end = map.constEnd();
        while (it != end) {
            sum += it.value();
            ++it;
        }
    }
    qint64 end2 = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "STL style iterator : \t" << (end2-start2) << " ms";


    qint64 start3 = QDateTime::currentMSecsSinceEpoch();
    for(int i = 0; i<nbIterations; ++i){
        sum = 0;
        auto end = map.cend();
        for (auto it = map.cbegin(); it != end; ++it)
        {
            sum += it.value();
        }
    }
    qint64 end3 = QDateTime::currentMSecsSinceEpoch();

    qDebug() << "STL style iterator v2 : \t" << (end3-start3) << " ms";
}

编辑2017年7月:我在我的新笔记本电脑(Qt 5.9,i7-7560U)上再次运行了这段代码,得到了一些有趣的变化

代码语言:javascript
复制
Reference vector :   155  ms 
Reference list :     157  ms
QMap::values():      1874  ms 
Java style iterator: 1156  ms 
STL style iterator:  1143  ms

在这个基准测试中,STL风格和Java风格具有非常相似的性能

票数 27
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8517853

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档