Reputation: 17120
I'm returning iterator from my fnc after I used it and this iterator at the point of returning points to some character but after this fnc returns it the returned iterator doesn't point to that character anymore. What am I doing wrong?
typename std::string::const_iterator return_iterator(const std::string& line)
{
auto beg = line.begin();
/*here I'm moving this iterator and assing to it i.e.*/
beg = line.begin() + some_position;
return beg;//at this point it points to a character
}
void other_fnc(const std::string& line)
{
auto pos = return_iterator(line);//after this fnc returns pos points to some rubbish
}
Any ideas?
Upvotes: 3
Views: 164
Reputation: 11542
I assume, the actual code probably has templates (typename
debris) and probably they are not referenced correctly in function argument of return type.
The following code works as expected:
const int some_position = 2;
template <typename T>
typename T::const_iterator return_iterator(const T& line)
{
typename T::const_iterator beg = line.begin();
beg = line.begin() + some_position;
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);
std::cout << "character to 2: " << *pos << std::endl;
}
int main()
{
std::string str = "Hello world";
other_fnc(str);
}
Verify your code according to it. If you are doing something else, update your question.
(PS: I got rid of auto
of C++11, as I don't have the compliant compiler at the moment)
Upvotes: 0
Reputation: 39208
As the example code that you posted does not compile (typename std::string::const_iterator
should be simply std::string::const_iterator
), and fixing this error allows the code to run as expected, I am guessing that the actual code is a bit different.
This sounds to me like a case of a std::string
parameter being copied by value and the reference counting being somehow disrupted before the const_iterator
is accessed. For example, this signature:
std::string::const_iterator return_iterator(std::string line)
// ^ Notice: Not passing by
// reference
passes the string by value. Because of COW, the copy is shared, but the moment that the function calls line.begin()
, the non-const string member function std::string::begin()
is called, meaning that a new copy of the underlying string is typically created. The non-const iterator
that is returned is then converted implicitly to a const_iterator
(a perfectly valid conversion).
EDIT: To demonstrate my point, take a look at the output of the following version that was modified to pass the line
parameter to return_iterator()
by value:
#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);
}
The assertion now fails. Also, notice that the addresses of *line.begin()
are different.
Upvotes: 1