Is there an authoritative way to guard against "use after move" mistakes in c++?

An effective rule of thumb: Never use std::move nor std::forward and never type cast to an rvalue (or universal) reference. If you never move from a variable or a reference, then you can't make the mistake of using it after. This approach obviously has a drawback, since those utilities are useful in some cases for turning a copy into a move when the move is sufficient; not to mention the cases where it is necessary.

Approach for your own types: Add assertions into member functions that verify whether the instance has been moved from, and rely on them to trigger during testing. The "moved" state will need to be stored as a member. Assertions and the member can be removed in release build. A drawback is that this adds otherwise unnecessary boilerplate to every member function.

An extra approach: Use a static analysis tool that attempts to detect the potential mistake.

A reasonable rule of thumb: Keep your functions short. When the function is short, a use will be close to the move, and thus the potential mistake is easier to spot.


So the issue really is "read" after move. I think I agree that any use of std::move should be code reviewed as a potential risk. If the std::move is at the end of a function with a local value or value parameter, all good.

Anything else needs scrutiny, and any use of the variable after the move should be given attention. I guess giving the variable an "_movable" suffix will also help with the code review.

The few cases of write after move, such as swap will just have to be defended during the review.

Personally, I still treat std::move as a smell in the code, much like casts.

I'm not sure of any lint rules that would enforce this pattern, but I'm sure they are easy to write :-)

Tags:

C++

C++11