Quick question: using numeric id's and STL maps, will C++ always iterate over the pairs in the order of the numeric id? Could this change depending on the compiler or is it guaranteed by the STL spec?
Example:
#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;
}
It doesn't matter which order I add the pairs in, they will always come out in numeric order in G++. Will this be the same across compilers?
Secondly, given the small size of the map, would it make any conceivable difference to performance if I were iterating over a std::string array[11] instead of a map? Scenario being iterating over the map 60 times per second with various other stuff going on.
EDIT: Thanks to Drino I have the answer, however testing has shown that in the case scenario where a map has fewer elements than the array, it may perform much better dependent on the number of elements. Please see the test code used below to achieve this, and apologies in advance for the SDL code, it was faster than hand-scripting my own milliseconds function in C++. Compiled using 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;
On this machine this routinely gives the output: num milliseconds array:14 num milliseconds map:11
Reversing the order of tests makes no difference. Removing the commented-out map insertions changes the results to the following: num milliseconds array:14 num milliseconds map:16
So, in the scenario where the number of map elements is variable or may not reach even half the maximum amount allowed, it may make more performant sense to use map instead of array, as the overhead of iterating the map is minor when the maximum is reached, but the benefits when the maximum is not reached are greater.