Для личного проекта я реализую свой собственный libstdc ++. Постепенно я добился хорошего прогресса. Обычно я буду использовать примеры из http://www.cplusplus.com/reference/ для некоторых базовых тестовых случаев, чтобы убедиться, что у меня очевидная функциональность работает должным образом.
Сегодня я столкнулся с проблемой с std::basic_string::replace
, в частности с версиями на основе итератора, использующими дословно скопированный пример с сайта (http://www.cplusplus.com/reference/string/string/replace/) ( Я добавил комментарий, чтобы указать на строки под вопросом ):
// replacing in a string
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string base="this is a test string.";
string str2="n example";
string str3="sample phrase";
string str4="useful.";
// function versions used in the same order as described above:
// Using positions: 0123456789*123456789*12345
string str=base; // "this is a test string."
str.replace(9,5,str2); // "this is an example string."
str.replace(19,6,str3,7,6); // "this is an example phrase."
str.replace(8,10,"just all",6); // "this is just a phrase."
str.replace(8,6,"a short"); // "this is a short phrase."
str.replace(22,1,3,'!'); // "this is a short phrase!!!"
// Using iterators: 0123456789*123456789*
string::iterator it = str.begin(); // ^
str.replace(it,str.end()-3,str3); // "sample phrase!!!"
// *** this next line and most that follow are illegal right? ***
str.replace(it,it+6,"replace it",7); // "replace phrase!!!"
it+=8; // ^
str.replace(it,it+6,"is cool"); // "replace is cool!!!"
str.replace(it+4,str.end()-4,4,'o'); // "replace is cooool!!!"
it+=3; // ^
str.replace(it,str.end(),str4.begin(),str4.end());
// "replace is useful."
cout << str << endl;
return 0;
}
В моей версии replace реализован в виде временной строки, которую я создаю, затем меняю местами *this
. Это явно делает недействительными любые итераторы. Так я прав, что пример неверен? поскольку он хранит итераторы, выполняет ли замену, а затем снова использует итераторы?
Моя копия стандарта (ISO 14882: 2003 - 21.3p5) гласит:
Ссылки, указатели и итераторы
ссылаясь на элементы
последовательность basic_string может быть
аннулированных
следующим использованием этого объекта basic_string:
- As an argument to non-member functions swap() (21.3.7.8),
operator>>() (21.3.7.9), and getline() (21.3.7.9).
- As an argument to basic_string::swap().
- Calling data() and c_str() member functions.
- Calling non-const member functions, except operator[](), at(),
begin(), rbegin(),
end(), and rend().
- Subsequent to any of the above uses except the forms of insert() and
erase() which return iterators,
the first call to non-const member functions operator[](), at(), begin(),
rbegin(), end(), or rend().
Кажется, запись о неконстантных функциях-членах охватывает это. Так что, если я что-то упустил, то этот код использует недействительные итераторы, верно? Конечно, этот код прекрасно работает с libstdc ++ от gcc, но мы все знаем, что ничего не доказывает, насколько соответствует стандартам.