Я обнаружил тревожное несоответствие между std :: string
и строковыми литералами в C ++ 0x:
#include <iostream>
#include <string>
int main()
{
int i = 0;
for (auto e : "hello")
++i;
std::cout << "Number of elements: " << i << '\n';
i = 0;
for (auto e : std::string("hello"))
++i;
std::cout << "Number of elements: " << i << '\n';
return 0;
}
Результат:
Number of elements: 6
Number of elements: 5
Я понимаю, почему это происходит: строковый литерал на самом деле представляет собой массив символов, который включает нулевой символ, и когда цикл for на основе диапазона вызывает std :: end ()
для символа массивон получает указатель за концом массива; поскольку нулевой символ является частью массива, он получает указатель за нулевым символом.
Однако я думаю, что это очень нежелательно: конечно std :: string
и строковые литералы должны вести себя одинаково когда дело доходит до таких основных свойств, как их длина?
Есть ли способ разрешить это несоответствие? Например, можно ли перегрузить std :: begin ()
и std :: end ()
для символьных массивов, чтобы ограничиваемый ими диапазон не включал завершающий нулевой символ? Если да, то почему этого не было сделано?
РЕДАКТИРОВАТЬ : Чтобы немного больше оправдать мое возмущение тем, кто сказал, что я просто страдаю от последствий использования строк в стиле C, которые являются «устаревшей функцией» рассмотрите следующий код:
template <typename Range>
void f(Range&& r)
{
for (auto e : r)
{
...
}
}
Ожидаете ли вы, что f ("hello")
и f (std :: string ("hello"))
сделают что-то другое?