c++:std::map数字id的迭代排序-交叉编译器

c++: std::map iterative ordering for numeric ids - cross-compiler

本文关键字:排序 编译器 迭代 std map 数字 id c++      更新时间:2023-10-16

快速问题:使用数字id和STL映射,C++是否总是按照数字id的顺序迭代这些对?这种变化可能取决于编译器,还是由STL规范保证?

示例:

#include <iostream>
#include <map>
#include <string>
int main(int argc, char **argv)
{
    std::map<int, std::string> testmap;
    testmap.insert(std::map<int, std::string>::value_type(0, "bob"));
    testmap.insert(std::map<int, std::string>::value_type(1, "jean"));
    testmap.insert(std::map<int, std::string>::value_type(2, "melissa"));
    testmap.insert(std::map<int, std::string>::value_type(3, "george"));
    testmap.insert(std::map<int, std::string>::value_type(4, "dave"));
    testmap.insert(std::map<int, std::string>::value_type(5, "sally"));
    testmap.insert(std::map<int, std::string>::value_type(6, "jessica"));
    testmap.insert(std::map<int, std::string>::value_type(7, "sandy"));
    testmap.insert(std::map<int, std::string>::value_type(8, "winston"));
    testmap.insert(std::map<int, std::string>::value_type(9, "pete"));
    testmap.insert(std::map<int, std::string>::value_type(10, "maxx"));
    for (std::map<int, std::string>::iterator map_item = testmap.begin(); map_item != testmap.end(); map_item++)
    {
        std::cout << map_item->second << std::endl;
    }
    std::cin.get();
    return 0;
}

我把这些对按哪个顺序加进去并不重要,它们总是以数字顺序出现在G++中。编译器之间的情况会相同吗?

其次,考虑到映射的大小很小,如果我迭代std::string数组[11]而不是映射,会对性能产生任何可能的影响吗?场景是每秒在地图上迭代60次,同时进行各种其他事情

编辑:多亏了Drino,我得到了答案,但测试表明,在映射的元素比数组少的情况下,它的性能可能会更好,这取决于元素的数量。请参阅下面用于实现这一点的测试代码,并提前为SDL代码道歉,它比用C++手工编写我自己的毫秒函数更快。使用mingw,g++4.8,-O2:编译

    std::map<int, std::string> testmap;
    std::string testarray[11];
    testmap.insert(std::map<int, std::string>::value_type(0, "bob"));
//    testmap.insert(std::map<int, std::string>::value_type(1, "jean"));
//    testmap.insert(std::map<int, std::string>::value_type(2, "melissa"));
//    testmap.insert(std::map<int, std::string>::value_type(3, "george"));
//    testmap.insert(std::map<int, std::string>::value_type(4, "dave"));
//    testmap.insert(std::map<int, std::string>::value_type(5, "sally"));
    testmap.insert(std::map<int, std::string>::value_type(6, "jessica"));
    testmap.insert(std::map<int, std::string>::value_type(7, "sandy"));
    testmap.insert(std::map<int, std::string>::value_type(8, "winston"));
    testmap.insert(std::map<int, std::string>::value_type(9, "pete"));
    testmap.insert(std::map<int, std::string>::value_type(10, "maxx"));
    testarray[0] = "bob";
    testarray[1] = "jean";
    testarray[2] = "melissa";
    testarray[3] = "george";
    testarray[4] = "dave";
    testarray[5] = "sally";
    testarray[6] = "jessica";
    testarray[7] = "sandy";
    testarray[8] = "winston";
    testarray[9] = "pete";
    testarray[10] = "maxx";
    SDL_Delay(2000); // Delay introduced to negate background effects of window creation and executable overhead
    Uint32 sdltime = SDL_GetTicks();
    unsigned int counter = 0;

    for (unsigned int looper = 0; looper != 100000; looper++)
    {
        for (unsigned int arrpos = 0; arrpos != 11; arrpos++)
        {
            if (testarray[arrpos] == "maxx")
            {
                counter++; // Included so the compiler doesn't optimise the loop out of existence.
            }
        }
    }
    std::cout << "num milliseconds array:" << SDL_GetTicks() - sdltime << std::endl;
    SDL_Delay(2000);  // Delay introduced to negate background effects of buffer out
    sdltime = SDL_GetTicks();
    counter = 0;

    for (unsigned int looper = 0; looper != 100000; looper++)
    {
        for (std::map<int, std::string>::iterator map_item = testmap.begin(); map_item != testmap.end(); map_item++)
        {
            if (map_item->second == "maxx")
            {
                counter++; // Included so the compiler doesn't optimise the loop out of existence.
            }
        }
    }
    std::cout << "num milliseconds map:" << SDL_GetTicks() - sdltime  << std::endl;

在这台机器上,它通常会输出:num毫秒数组:14num毫秒映射:11

颠倒测试顺序没有什么区别。删除注释掉的映射插入会将结果更改为以下内容:num毫秒数组:14num毫秒映射:16

因此,在映射元素的数量是可变的,或者可能甚至达不到允许的最大数量的一半的情况下,使用映射而不是数组可能更有性能,因为当达到最大值时迭代映射的开销很小,但当未达到最大值时利益更大。

  1. 是的,订单是一样的。std::map使用键的顺序来存储数据(在C++11中有一个unrdered_map,它忽略了顺序),所以当你迭代它时,较小的优先
  2. 对于这样小的数据集,数组(或向量或列表)将比映射快得多

[EDIT:除非映射的元素较少(基准)。根据存在的元素数量,程序在映射上的迭代速度可能比数组快得多。]

您使用映射将线性索引存储为键。只需使用vectorarray。你不应该关心map存储物品的顺序,它总是会以最有效的方式进行,你不应该对此承担任何责任。

你也可以这样插入地图:

testmap[0] = "bob";

或者像这样:

testmap.insert(std::make_pair(1, "bob"));