Поскольку код примера, который вы опубликовали, не компилируется (typename std::string::const_iterator
должен быть просто std::string::const_iterator
), и исправление этой ошибки позволяет коду работать как положено , я предполагаю, что фактический код немного отличается.
Для меня это звучит как случай, когда параметр std::string
копируется по значению, а подсчет ссылок каким-то образом прерывается до получения доступа к const_iterator
. Например, эта подпись:
std::string::const_iterator return_iterator(std::string line)
// ^ Notice: Not passing by
// reference
передает строку по значению. Из-за COW копия является общей, но в тот момент, когда функция вызывает line.begin()
, вызывается неконстантная функция-член строки std::string::begin()
, что означает, что новая копия базовой строки обычно создано. Возвращаемое неконстантное значение iterator
затем неявно преобразуется в const_iterator
(совершенно правильное преобразование).
РЕДАКТИРОВАТЬ: Чтобы продемонстрировать мою точку зрения, взгляните на вывод следующей версии, которая была изменена для передачи параметра line
в return_iterator()
по значению:
#include <cassert>
#include <string>
#include <iostream>
std::string::const_iterator return_iterator(std::string line)
{
std::string::const_iterator beg = line.begin();
std::cout << "In return_iterator(), &(*line.begin()) is " << static_cast<const void *>(&*beg) << '\n';
/*here I'm moving this iterator and assing to it i.e.*/
beg = line.begin() + 3;
return beg;//at this point it points to a character
}
void other_fnc(const std::string& line)
{
std::string::const_iterator pos = return_iterator(line);//after this fnc returns pos points to some rubbish
std::cout << "In other_fnc(), &(*line.begin()) is " << static_cast<const void *>(&*line.begin()) << '\n';
assert(*pos == line[3]);
}
int main()
{
std::string line = "This is a test.";
other_fnc(line);
}
http://codepad.org/K9yaWqWA
Утверждение теперь не выполняется. Также обратите внимание, что адреса *line.begin()
отличаются.