Ключ карты строки C

Есть ли проблема с использованием строки C в качестве ключа карты?

std::map<const char*, int> imap;

Порядок элементов на карте не имеет значения, поэтому все в порядке, если они упорядочены с использованием std::less<const char*>,

Я использую Visual Studio и в соответствии с MSDN (Microsoft):

В некоторых случаях идентичные строковые литералы могут быть «объединены» для экономии места в исполняемом файле. В пуле строковых литералов компилятор заставляет все ссылки на определенный строковый литерал указывать на одно и то же место в памяти, вместо того, чтобы каждая ссылка указывала на отдельный экземпляр строкового литерала.

Это говорит о том, что они только объединены в некоторых случаях, так что кажется, что получить доступ к элементам карты с помощью строкового литерала было бы плохой идеей:

//Could these be referring to different map elements?
int i = imap["hello"];
int j = imap["hello"];

Можно ли перегрузить operator== за const char* так что фактическая строка C, а не значения указателя будет использоваться для определения, равны ли элементы карты:

bool operator==(const char* a, const char* b)
{
return strcmp(a, b) == 0 ? true : false;
}

Является ли когда-нибудь хорошей идеей использовать строку C в качестве ключа карты?

3

Решение

Можно ли перегрузить оператор == для const char *, чтобы фактическая строка C, а не значения указателя использовались для определения, равны ли элементы карты

Нет, это не так, и да, это не очень хорошая идея именно по той причине, которая указана в вопросе. а также потому что тебе не нужно char*Вы можете использовать std::string вместо. (вы можете предоставить пользовательскую функцию сравнения — как указано в simonc, но я бы посоветовал против этого)

//Could these be referring to different map elements?
int i = imap["hello"];
int j = imap["hello"];

Да, и они могут даже ссылаться на элементы, которые еще не существуют, но они будут созданы operator[] и значение будет инициализировано. Та же проблема существует с назначением:

imap["hello"] = 0;
imap["hello"] = 1;

Карта теперь может иметь 1 или 2 элемента.

4

Другие решения

Вы можете предоставить карту с пользовательским компаратором, который сравнивает строки C

std::map<const char*,YourType,CstrCmp>;

bool CstrCmp::operator()(const char* a, const char* b)
{
return strcmp(a, b) < 0;
}
5

Во-первых, чтобы ввести упорядочение по ключам карты, необходимо определить сравнение «меньше, чем». Карта говорит, что два элемента «эквивалентны», если ни один не меньше другого. Это плохая идея использовать char * для ключей карты, потому что вам нужно будет управлять памятью где-то за пределами карты.

В большинстве реалистичных сценариев при запросе карты ваши ключи не будут литералами.

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

Подводя итог, я бы не стал полагаться на то, что Microsoft говорит: «В некоторых случаях литералы могут объединяться». Если вы заполняете карту литералами и запрашиваете карту с литералами в качестве ключей, вы также можете использовать enum для ключей.

1
По вопросам рекламы [email protected]