Std :: map.count с использованием c-строк не работает?

Я хочу использовать c-строки вместо std::string для ситуации производительности. У меня есть следующий код:

std::map<const char*,="" int=""> myMap;
.
.
.
myMap.insert(std::pair<const char*,="" int="">(str.c_str(), *****));
std::cout << myMap.count(str.c_str()) << std::endl;
</const></const>

Как ни странно, только что введенное значение возвращает 0 для count()?

3 ответа

Почему вы думаете, что использование необработанных строк C приведет к увеличению производительности?

В любом случае, std::map не имеет специальной обработки указателей на char. Он рассматривает их как любой другой указатель, а не как строки, а это означает, что он просто сравнивает ключи с std::less. Возможно, смутно, это отличается от поведения потоков C++, которые ведут себя особым образом при передаче char const *.

Вы получите такое же поведение, как std::map, std::map или std::map. Интересно отметить, что сравнение указателей работает, потому что std::less гарантированно работает с указателями, хотя сравнение указателя с < является формально неопределенным поведением.

Таким образом, вам явно не интересно напрямую сравнивать значения указателя. Если вы хотите сравнить лексикографические строки, вы можете указать сравнение для своей карты с помощью третьего параметра шаблона:

std::map

То, что я назвал RawPointerComparison в этом примере, должно быть функтором, принимающим два указателя и возвращающим, является ли первое меньше второго. Вы можете использовать функцию strcmp C для этого. Это должно сделать трюк:

struct RawPointerComparison
{
 bool operator()(char const *lhs, char const *rhs) const
 {
 return strcmp(lhs, rhs) < 0;
 }
};


Кажется, что вы используете переменную str для ввода разных строк на карте. Например

str = "first";
myMap.insert( { str.c_str(), 1 } );

str = "second";
myMap.insert( { str.c_str(), 2 } );

str = "first";
std::cout << myMap.count(str.c_str()) << std::endl;

В этом случае первая str.c_str() не равна последней str.c_str() (где вы сравниваете указатели на выделенные строки), потому что в этих случаях были выделены разные области памяти.

Если вы сделаете следующее

str = "first";
myMap.insert( { str.c_str(), 1 } );
std::cout << myMap.count(str.c_str()) << std::endl;

без промежуточных операторов, то результатом будет выход 1.

Кажется, вы делаете то, чего не хотите. :)


По умолчанию std::map использует std::less чтобы сравнить ключи (что то же самое, что и <, действительно, за исключением того, что он гарантированно работает и с несвязанными указателями). Это означает, что это просто сравнение указателей, определенно не то, что вы хотите.

Просто используйте строковый тип С++ 11 (std::string) вместо старого типа, используемого для строк с nul-terminated (const char*), и все будет в порядке.

licensed under cc by-sa 3.0 with attribution.