Pregunta

Something a lot of C++ programmers miss (read: me) when first using stringstreams is the fact that the copy returned by stringstream::str() is a temporary, which lasts until the end of the expression it's used in. However, I don't understand:

  1. How this is done. Looking in the sstream header for libstdc++, I only see a copy being made and returned. How is the lifetime restricted?
  2. Why this is the desired behavior, especially since it is such a common gotcha. If a copy is being made anyway, why can't I take ownership of it?

Note that this is not a duplicate of stringstream, string, and char* conversion confusion. That goes over explaining the behavior and workarounds; I'm looking for mechanics and rationale.

¿Fue útil?

Solución

This is not a problem of stringstream. It is the problem of c_str function - it returns pointer to a char* representation of std::string, but it lives only during lifetime of an original string. When you call char *str = ss.str().c_str() the following actually happens:

string tmp = ss.str();
char *str = tmp.c_str();
tmp.~string (); // after that line the pointer `str` is no longer valid

c_str is a dangerous function provided only for compatibility and speed purposes and you should avoid using it.

Otros consejos

stringstream::str() returns a string. Period. It does so by value, so you can do whatever you want with it (e.g. certainly take ownership).

How this is done? Looking in the sstream header for libstdc++, I only see a copy being made and returned. How is the lifetime restricted?

str() returns by value, meaning the object it returns is destroyed by the end of the full expression. It's simply the way temporaries work.

Why this is the desired behavior, especially since it is such a common gotcha. If a copy is being made anyway, why can't I take ownership of it?

It's an amendment from the traditional IOStreams. The old deprecated class of streams strstream had an str() method that returned a pointer to its internal buffer. To protect against invalidation of the pointer, the stream had to be "frozen", meaning the buffer could not be resized.

The Standard IOStreams returns a copy of the buffer as a std::basic_string<charT> object so that freezing the stream is no longer necessary.

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