
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
56 lines
2.0 KiB
Plaintext
56 lines
2.0 KiB
Plaintext
== Why is this an issue?
|
|
|
|
`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
|
|
|
|
[source,cpp]
|
|
----
|
|
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
|
|
|
|
[source,cpp]
|
|
----
|
|
void f(A &&a) {
|
|
g(std::move(a.name)); // Compliant, `a.name` is in moved-from state, `a` itself is not
|
|
----
|
|
|
|
=== Exceptions
|
|
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:
|
|
|
|
[source,cpp]
|
|
----
|
|
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
|
|
};
|
|
}
|
|
----
|
|
|