51 lines
2.0 KiB
Plaintext
51 lines
2.0 KiB
Plaintext
![]() |
`std::move` is not really moving anything, but tells the compiler that a value can be considered as no longer useful. It is technically a cast to a RValue, and allows overload resolution to select the version of a function that will perform destructive operations on that value (therefore actually moving from it).
|
||
|
|
||
|
----
|
||
|
void f(A const &a); // Just reading from a
|
||
|
void f(A&& a); // I can perform destructive operations on a, like resource stealing
|
||
|
|
||
|
void g() {
|
||
|
A a;
|
||
|
f(a); // First overload is selected
|
||
|
f(std::move(a)); // Second overload is selected
|
||
|
}
|
||
|
----
|
||
|
|
||
|
As a consequence, calling `std::move` on an object and then not directly using the returned value as a function argument is not the typical pattern, and may be indicative of a bug. Note that calling a member function on the result of `std::move` _is_ considered as passing it to a function (as the hidden `this` parameter), as well as using it as an operand (the called function is the overloaded operator) or initializing an object with it (the called function is the constructor).
|
||
|
|
||
|
== Noncompliant Code Example
|
||
|
|
||
|
----
|
||
|
void sink(A &&a) {
|
||
|
std::move(a); // Noncompliant, and not doing anything
|
||
|
}
|
||
|
|
||
|
void f(A &&a) {
|
||
|
// May or may not move the member name, depending on its type, the intent is not clear anyways,
|
||
|
// for instance, is `a` supposed to be in a moved-from state after the call?
|
||
|
g(std::move(a).name); // Noncompliant
|
||
|
}
|
||
|
----
|
||
|
|
||
|
== Compliant Solution
|
||
|
|
||
|
----
|
||
|
void f(A &&a) {
|
||
|
g(std::move(a.name)); // Compliant, `a.name` is in moved-from state, `a` itself is not
|
||
|
----
|
||
|
|
||
|
== Exception
|
||
|
Even if calling a built-in operator or initializing data of built-in type are not function calls, for consistency with cases that involve user-defined types, this rule will not report in those cases:
|
||
|
|
||
|
----
|
||
|
struct Data {A a; int b; };
|
||
|
|
||
|
Data add(Data &&d1, Data &&d2) {
|
||
|
return Data{
|
||
|
std::move(d1.a) + std::move(d2.a), // Compliant, operator+ might have an overload for A&&
|
||
|
std::move(d1.b) + std::move(d2.b) // Compliant by exception
|
||
|
};
|
||
|
}
|
||
|
----
|
||
|
|