Я обнаружил тревожное несоответствие между 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
Я понимаю, почемуэто происходит: строковый литерал на самом деле представляет собой массив символов, который содержит нулевой символ, и когда основанный на диапазоне цикл вызывает 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"))
сделают что-то другое?