Адрес значения карты - PullRequest
       6

Адрес значения карты

4 голосов
/ 23 ноября 2011

У меня есть настройки, которые хранятся в std::map. Например, есть ключ WorldTime со значением, который обновляет каждую итерацию основного цикла. Я не хочу читать его с карты, когда мне это нужно (он также обрабатывает каждый кадр), я думаю, что это не быстро Итак, могу ли я получить указатель на значение карты и получить к нему доступ? Код:

std::map<std::string, int> mSettings;

// Somewhere in cycle:
mSettings["WorldTime"] += 10; // ms

// Somewhere in another place, also called in cycle
DrawText(mSettings["WorldTime"]); // Is slow to call each frame

Так что идея примерно такая:

int *time = &mSettings["WorldTime"];

// In cycle:
DrawText(&time);

Насколько это неправильно? Должен ли я сделать что-то подобное?

Ответы [ 3 ]

5 голосов
/ 23 ноября 2011

Лучшее использование ссылки:

int & time = mSettings["WorldTime"];

Если ключ еще не существует, доступ [] создаст элемент (и инициализирует отображаемое значение, то есть 0 для int). В качестве альтернативы (если ключ уже существует):

int & time = *mSettings.find("WorldTime");

Как отступление: если у вас есть сотни тысяч строковых ключей или вы часто используете поиск по строковому ключу, вы можете обнаружить, что std::unordered_map<std::string, int> дает лучшие результаты (но всегда профилирует перед принятием решения). Две карты имеют практически идентичные интерфейсы для ваших целей.

3 голосов
/ 23 ноября 2011

Согласно этому ответу в StackOverflow , вполне нормально хранить указатель на элемент карты, поскольку он не будет аннулирован, пока вы не удалите элемент (см. Примечание 3).

1 голос
/ 23 ноября 2011

Если вы так сильно беспокоитесь о производительности, то почему вы используете строки для ключей? Что делать, если у вас был enum? Как это:

enum Settings 
{
    WorldTime, 
    ... 
}; 

Тогда ваша карта будет использовать целые числа для ключей, а не для строк. Он должен сравнивать ключи, потому что я считаю, что std :: map реализован в виде сбалансированного дерева. Сравнения между целыми числами намного быстрее, чем сравнения между строками.

Кроме того, если вы используете enum для ключей, вы можете просто использовать массив, потому что enum - это, по сути, карта от некоторого вида символа (например, WorldTime) до целого числа, начиная с нуля. Итак, сделайте это:

enum Settings 
{
    WorldTime, 
    ... 
    NumSettings
}; 

А затем объявите ваши mSettings как массив:

int mSettings[NumSettings];

Который имеет более быстрое время поиска по сравнению с std :: map. Ссылка вот так:

DrawText(mSettings[WorldTime]);

Поскольку вы в основном просто получаете доступ к значению в массиве, а не к карте, это будет намного быстрее, и вам не нужно беспокоиться о хакере указателя / ссылки, который вы пытались сделать в первом место.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...