20

Consider the following example:

#include <sstream>
template <typename T>
inline std::string to_string(T const & op) {
    std::ostringstream result;
    result << op;
    return result.str();
}

If I was to return result, instead of result.str() it would automatically become an rvalue. Not so the string contained in in result (I assume). My expectation is that it is copied and the copy returned as an rvalue.

So my question here is, is it legal to:

return std::move(result.str());

I would assume it is, expecting the stream to be left with a valid, empty string. But I do not feel certain enough to actually do it.

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
kamikaze
  • 1,529
  • 8
  • 18
  • 13
    Calling `std::move(e)` in a return statement is an anti-pattern. The returned expression is implicitly treated as an rvalue anyway and using `std::move` inhibits copy-elision. – TartanLlama Mar 01 '16 at 15:29
  • 2
    @TartanLlama aren't you oversimplifying? What if there was a function "std::string std::ostringstream::str() &&", wouldn't the best way to leave the function a "return std::move(result).str();"? – kamikaze Mar 01 '16 at 15:48
  • @kamikaze Yeah, as Baum says I was referring to the pattern where all you have in your return statement is `std::move(e)`, where `e` is some expression. – TartanLlama Mar 01 '16 at 15:57
  • 3
    @kamikaze `return move(e)` (bad) != `return move(e).smth()` (might (very rarely) make sense). (Partially reposted because of edit.) – Baum mit Augen Mar 01 '16 at 15:59
  • should it be okay to std::move to a parameter to a function? `void some_func (std::string &output) { std::stringstream ss; ....... output = std::move(ss.str()); }` – vk-code Dec 05 '18 at 16:19

1 Answers1

24

std::ostream::str indeed returns a copy of the internal string. So the move is legal, but it makes no sense as result.str() is an rvalue anyway and thus the std::move does nothing useful. If anything, it hinders RVO, so don't do it. (As @TartanLlama correctly pointed out in their comment, "Don't move the return value" holds true in general, not just when returning rvalues.)

In particular, the std::move does not affect the internal string object of the stream.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • That was embarrassingly easy. For some reason I thought it returns a reference. – kamikaze Mar 01 '16 at 15:32
  • 1
    @kamikaze When in doubt or to double check consult the [documentation](http://en.cppreference.com/w/cpp/io/basic_stringstream/str) – NathanOliver Mar 01 '16 at 15:33
  • 1
    @kamikaze That's what we have [documentation](http://en.cppreference.com/w/cpp/io/basic_ostringstream/str) for. ;) – Baum mit Augen Mar 01 '16 at 15:33
  • Though if you wanted to prevent return value optimization and copy elision for whatever reason, this would be the way to do it. – callyalater Mar 01 '16 at 15:34