When exactly does an object cast with std::move
d get moved?
For instance, does the following code constitute use after move?
f(std::move(a), a.Something())
Where f
= f(A a, int x)
and a
is an instance of some class.
I understand that std::move(a)
may be evaluated before a.Something()
, but when does the actual move itself occur?
14
When exactly does an object cast with std::moved get moved?
It depends on how the reference returned by std::move()
is being used. std::move()
itself doesn’t do anything, it is just a type-cast, nothing more. The actual move happens when something else receives that reference and decides to move the refered-to object’s data.
For instance, does the following code constitute use after move?
f(std::move(a), a.Something())
Where
f
=f(A a, int x)
anda
is an instance of some class.
It CAN, but the order of evaluation of function parameters is not guaranteed. std::move(a)
MAY be evaluated first, or a.Something()
MAY be evaluated first. What is guaranteed is only that both parameters will have been fully evaluated before f()
is actually entered.
I understand that
std::move(a)
may be evaluated beforea.Something()
, but when does the actual move itself occur?
Since the A a
parameter is being passed into f()
by value, a temporary object must be constructed for it. A move CAN happen if the return value of std::move()
is used to move-construct that object, but only if the A(A&&)
constructor is implemented (either implicitly by the compiler, or explicitly in A
‘s code), and it actually performs a move. Without that constructor, the object will be copy-constructed instead, and thus no move will happen.
2
This line:
f(std::move(a), a.Something());
Can indeed constitute a use after move.
If your f
is:
f(A a, int x) { ... }
Then the first argument will have to be either copied or moved into the parameter A a
before invoking f
. This means that the actual move can also take place before a.Something()
is evaluated, causing a use after move.
It’s worth nothing that if your f
was e.g.:
f(A && a, int x) { ... }
Then you would be safe, because std::move
itself is just a cast to rvalue ref which is what is expected for A && a
, and therefore no move would actually take place at the stage of evaluating the arguments for f
.