Отличный вопрос!
Причина в том, что строка в стиле C определяется как последовательность байтов, которая заканчивается нулевым байтом. Когда вы используете .c_str()
, чтобы получить строку в стиле C из C ++ std::string
, вы возвращаете последовательность, хранящуюся в строке C ++, с нулевым байтом после нее. Когда вы передаете это в strlen
, оно будет сканировать байты, пока не достигнет нулевого байта, а затем сообщит, сколько символов было найдено до этого. Если string
содержит нулевой байт, то strlen
сообщит о значении, которое меньше всей длины строки, так как оно остановится, прежде чем достигнет реального конца строки.
Важной деталью является то, что strlen
и char_traits<char>::length
НЕ являются одной и той же функцией. Однако спецификация C ++ ISO для char_traits<charT>::length
(& sect; 21.1.1) гласит, что char_traits<charT>::length(s)
возвращает наименьшее i
, так что char_traits<charT>::eq(s[i], charT())
имеет значение true. Для char_traits<char>
функция eq
просто возвращает, если два символа равны, выполняя сравнение ==
, а построение символа с помощью записи char()
дает нулевой байт, и это равносильно произнесению «где первый нулевой байт в строке? " По сути, это то, как работает strlen
, хотя эти две функции технически разные.
C ++ std::string
, однако, это более общее понятие «произвольной последовательности символов». Подробности его реализации скрыты от внешнего мира, хотя, вероятно, он представлен либо указателем начала и конца, либо указателем и длиной. Поскольку это представление не зависит от того, какие символы хранятся, запрос std::string
о его длине говорит вам, сколько символов существует, независимо от того, какие символы на самом деле есть.
Надеюсь, это поможет!