As my team move towards embracing the new features in C++11, I'm struggling with how to make the side-effects of std::move self-documenting in the code.

The issue is that an object that has been moved should no longer be used after that point. All I can come up with is a comment:

std::string x = Func();
Other(x);   // x is zombied.

Obviously this is error-prone and will not handle the cases where deeper code might unwittingly do a std::move.

Has anyone else dealt with this issue?

I have a feeling that diagnosing the use of zombied objects could be as much a pain as tracking down leaks or heap corruption.

  • What definition of Other would allow it to move out of x?
    – user7043
    Nov 25, 2013 at 10:54
  • @delnan Technically, void Other(std::string &). Semantically, I think none. As Jan correctly says, that’s simply a bug. Nov 25, 2013 at 17:29

2 Answers 2


The r-value reference only binds to rvalues. In the above code, Other(std::string &&) will not be considered. So only problem might be if the function std::string & but moved it internally.

The only way to get r-value out of l-value is a std::move. So as long as you take care not to use std::move on function argument you received by l-value reference, there will be no surprises.

Moving something you received by l-value reference should be considered a bug. Unfortunately the rules of the language itself are unable to catch it, so it's a job for a static checker. I don't know whether any of them does already though.

Of course a function taking a non-const l-value reference could always screw up the passed object and the move just adds another way to do it, but the problem already existed.

I would generally recommend avoiding functions taking non-const l-value references, because functions modifying their argument are never particularly readable. A method is expected to modify it's invocant (unless it's a getter), but modifying other arguments makes the data flow more complicated and less obvious. In C++11 move makes returning objects almost as efficient as modifying reference and std::tuple with std::tie allow returning multiple values, so most uses of argument modifying can be rewritten without significant loss of efficiency.

As for proper use of std::move note that most efficient way to write setters that were previously written taking const reference and copied from it should now take by value and move from it. The argument construction in caller will do move if possible and copy otherwise.

  • The latter is the situation that's beginning to occur.
    – James
    Nov 25, 2013 at 12:32
  • @James: That's something to avoid, not document.
    – Jan Hudec
    Nov 25, 2013 at 15:14
  • IMHO, if you don't want your argument changed by a callee - you either pass it by value, make sure arg is const or pass a copy. If you are passing as l-ref to non-const - then it's a fair game...
    – Eugene
    Nov 25, 2013 at 23:19
  • @Eugene: Well, a function taking non-const l-value reference is a rather strong code smell. Methods are generally expected to modify their invocant, but functions shouldn't modify their arguments. Especially in C++11 where move makes the more readable approach almost as efficient.
    – Jan Hudec
    Nov 26, 2013 at 7:10
  • @Eugene: Your note is good in that it shows the problem already existed before move semantics. Moving from the object adds another way to screw it, but other ways existed before.
    – Jan Hudec
    Nov 26, 2013 at 7:27

Don't hide the move, write it like this:

std::string x = Func();
  • That requires changing the signature of Other. Yes, the signature should be changed, but it is important to mention it.
    – Jan Hudec
    Nov 26, 2013 at 7:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.