Pregunta

I try to generalize for stream objects with following code:

#include <iostream>
#include <vector>
#include <sstream>
#include <iterator>

using namespace std;

template<class T, class U>
T& operator<<(T& os, vector<U> vec)
{
    vector<string>::iterator begin = vec.begin();
    vector<string>::iterator end = vec.end();
    for (; begin != end; ++begin)
        os << *begin << " ";
    return os;
}

int main()
{
    vector<string> things({
        "car", "truck", "rabbit"
    });

    ostringstream oss;
    oss << things << endl;
    copy(oss.str().begin(), oss.str().end(), ostream_iterator<char>(cout, ""));
}

Now it work with cout << things and string str = oss.str(); copy(str.begin() ... but not with oss.str().begin(). From what I understand, str() returns a string object with a copy of the current contents of the stream. So why do we need to copy it twice, once from str() and once in initialization of string object? This question is not same as using c_str().

Following also works:

string::iterator begin = oss.str().begin();
string::iterator end = oss.str().end();
copy(begin, end, ostream_iterator<char>(cout, ""));
¿Fue útil?

Solución

From what I understand, str() returns a string object with a copy of the current contents of the stream.

That is correct. And it is the answer to your question. Because str() returns a copy, two calls to oss.str() result in two completely different copies (i.e. two different string objects). The iterators of the two respective string objects are not compatible, since they are not from the same string. It is undefined behavior to pass two iterators from two completely different strings to an algorithm (such as std::copy) which is expecting them to be from the same range.

You wouldn't expect this to work, would you?

std::string str1 = oss.str();
std::string str2 = oss.str();
std::copy(str1.begin(), str2.end(), ostream_iterator<char>(cout, ""));

In response to your edit, "Following also works:". If that works, it is purely by coincidence. Those iterators are both invalid at the end of the statement in which they were created, because the string into which they point no longer exists. Your use of them in the call to std::copy is undefined behavior.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top