Ракссмотрим простой пример.
const int N = 5;
int a[N] = { 1, 2, 3, 4, 5 };
for ( int i = 0; i < N; i++ ) std::cout << a << std::endl;
В описании индексного оператора в стандарту C++ записано, что
цитата: |
E1[E2] is identical (by definition) to *((E1)+(E2)) |
|
Возвращаясь к примеру цикла, его можно переписать следующим образом
цитата: |
for ( int *p = a; p != a + N; ++p ) std::cout << *p << std::endl; |
|
Эти две записи одного и того же цикла эквивалентны.
Теперь обратимся к описанию индексного оператора для стандартного класса
std::string в стандарте C++.
цитата: |
const_reference operator[](size_type pos) const; reference operator[](size_type pos); 1 Requires: pos <= size(). 2 Returns: *(begin() + pos) if pos < size(). Otherwise, returns a reference to an object of type charT with value charT(), where modifying the object leads to undefined behavior. 3 Throws: Nothing. 4 Complexity: constant time. |
|
Из этого описания следует, что вы можетте обращаться к элементу объекта типа
std::string следующим образом:
std::string s( /* some string literal */ );
s[s.size()];
Или если строка пустая, то
std::string s;
s[0];
Более того вы можете написать следующий код
char *p = s.data();
while ( *p ) ++p;
То есть вы можетте обращаться к элементу
s.data() + s.size() или
*( &s[0] + s.size() ), хотя не можете (то есть стандартом не разрешается) изменять этот элемент. То есть согласно стандарту C++ 2011 завершающий символ
'\0' теперь является частью хранимой в классе
std::string строки.
К тому же никто не запрещает итератор класса
std::string определить просто как
char * Итак, вы можете записать
for ( char *p = &s[0]; *p; ++p ) { /* ... */ }
и в то же самое время вы не можете так записать если итератором является
char * for ( std::string::iterator p = s.begin(); *p; ++p ) { /* ... */ }
Хотя эти записи полностью эквивалентны, если итератор в классе
std:;string определен как
char * Действительно, мы можем переписать цикл
for ( char *p = &s[0]; *p; ++p ) { /* ... */ }
в виде
for (auto p = s.begin(); *p; ++p ) { /* ... */ }
Чем является
p в этом цикле? С одной стороны, это
std::string::iterator, с другой стороны, это
char * Получается, что стандарт заявляет, что данное предложение
for ( char *p = &s[0]; *p; ++p ) { /* ... */ }
корректное, и в то же самое время он заявляет, что данное предложение некорректное, так как никто нам не запрещает определеить
std::string::iterator! как
char *!
Я написал об этом очевидном на мой взгляд противоречии стандарта на форуме по обсуждению стандарта C++. Но, похоже, до членов комитета по стандартизации С++ это доходит со скрипом!