MISRA C++:2023 Rule 28.6.3
Description
Rule Definition
An object shall not be used while in a potentially moved-from state.
Rationale
If you convert an lvalue reference to rvalue reference by using
std::move()
or std::forward
, the original
lvalue reference remains in a potentially moved-from state, which can be an
indeterminate state. In this code, the object original
is passed as
an lvalue reference to foo()
, which converts the lvalue reference to
an rvalue reference:
class myobj {/**/ }; void foo(myobj &A) { myobj B{std::move(A)} } void bar() { myobj original; foo(original) }
foo()
is called the object
original
is in an indeterminate state. Using the
original
object can have unexpected results.Avoid using objects while they are in a potentially moved-from state. If your function accepts a lvalue reference, avoid keeping them in a move-from state when the function returns.
This rule does not apply when:
You use a
std::unique_ptr
. The mover-from state ofstd::unique_ptr
is well-defined and equal tonullptr
.You assign a value to the potentially moved-from object.
You destroy the potentially moved-from object.
Polyspace Implementation
The rule checker reports a violation of this rule if any of these conditions are true:
An object is read after its contents are moved to a destination object by calling the
std::move
function explicitly.An object forwarded by explicitly calling
std::forward
is reused after the call. Polyspace® does not flag the call tostd::forward
if its argument is reused in a branch that cannot be reached after the call tostd::forward
. For example, in this code snippet, the branch where the reuse of variablet
occurs cannot be reached after the execution enters the branch wherestd::forward
is used.template<typename T> void func(T&& t) { T&& p = t; switch(t) { case 0: p = std::forward<T>(t); break; case 1: t--; //t reused break; } }
An lvalue reference parameter of a function is moved-from in the function body.
Polyspace does not flag accessing a source object after its contents are moved if any of these conditions are true:
The source object of an explicit move operation is one of these types:
std::unique_ptr
std::shared_ptr
std::weak_ptr
std::basic_ios
std::basic_filebuf
std::thread
std::unique_lock
std::shared_lock
std::promise
std::future
std::shared_future
std::packaged_task
The move operation is performed implicitly. For example, the function
std::remove
moves objects implicitly. Polyspace does not flag accessing the object moved implicitly. To avoid accidentally accessing a moved object, erase the removed object by usingstd::erase
. For details about usingstd::remove
, seeImproper erase-remove idiom
.The source object is of a built-in base type, such as:
int
,enum
,float
,double
,std::intptr_t
,std::nullptr_t
, and pointer types.
Troubleshooting
If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.
Examples
Check Information
Group: Algorithms Library |
Category: Required |
Version History
Introduced in R2024b