Ключ карты строки 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 в качестве ключа карты?


person user974967    schedule 13.12.2012    source источник


Ответы (3)


Можно ли перегрузить operator== для 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 элемента.

person Luchian Grigore    schedule 13.12.2012

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

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

bool CstrCmp::operator()(const char* a, const char* b) const
{
    return strcmp(a, b) < 0;
}
person simonc    schedule 13.12.2012
comment
Я знаю, что компаратор используется для определения положения элементов на карте, но он также используется для определения равенства двух элементов карты? Другими словами, если вы укажете компаратор, он будет использоваться вместо оператора ==, чтобы определить, равны ли два элемента карты? - person user974967; 13.12.2012
comment
Карта говорит, что два элемента эквивалентны, если ни один из них не меньше другого. Так, например, если ваше сравнение строк нечувствительно к регистру, карта может содержать abc или ABC, но не оба. - person Alexander Chertov; 13.12.2012
comment
@user974967 user974967 operator== никогда не используется ни для чего на карте: это всегда предоставленный компаратор, который по умолчанию равен std::less. Карте нужен один и только один критерий для корректной работы. - person Gorpik; 13.12.2012

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

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

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

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

person Alexander Chertov    schedule 13.12.2012