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

时间:2014-04-09 00:41:32

标签: c++ performance sorting map stl

快速提问: 使用数字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毫秒数组:14 num milliseconds map:11

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

因此,在地图元素的数量可变或者可能达不到允许的最大量的一半的情况下,使用地图而不是数组可能会提高性能,因为迭代地图的开销很小。达到最大值,但未达到最大值时的好处更大。

2 个答案:

答案 0 :(得分:2)

您正在使用地图将线性索引存储为关键字。只需使用vectorarray即可。您不应该关注map存储项目的顺序,它总是以最有效的方式执行,您不应该对此做任何假设。

您也可以像这样插入地图:

testmap[0] = "bob";

或者像这样:

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

答案 1 :(得分:2)

  1. 是的,订单会一样。 std :: map使用键的顺序来存储数据(在C ++ 11中有unordered_map,它忽略了顺序),所以当你迭代它时,small会先行。
  2. 对于这样的小数据集,数组(或向量或列表)将比地图快得多。
  3. [编辑:除了地图中元素较少(基准)的情况。根据存在的元素数量,程序可以比数组快得多地迭代地图。]