CERT.EXPR.MOVED_FROM.USE

Do not use a moved-from object

This checker is applicable only to the modern engine.

The CERT.EXPR.MOVED_FROM.USE checker detects use-after-move defects in C++ programs (C++11 and later). When std::move is applied to an object and the result is consumed (passed to a move constructor or move assignment operator), the source object enters a valid but unspecified state. Any subsequent use of that moved-from object, such as reading its value, invoking a non-reinitializing member function, or passing it to a consuming function, relies on an unspecified value and therefore produces unspecified or undefined behavior.

Vulnerability and risk

The C++ standard guarantees only that a moved-from object is in a valid but unspecified state — it is safe to destroy or reassign, but its value is unspecified. Accessing a moved-from std::string may yield an empty string or any other value, silently corrupting output. Accessing a moved-from std::vector is typically empty, causing range loops and index-based accesses to silently process no elements or go out of bounds. Passing a moved-from object to a function that expects a valid value silently propagates the unspecified state further into the call chain. In multi-step pipelines, the defect is often far from the move site, making it difficult to diagnose without a tool.

Mitigation and prevention

Do not read or call non-trivial methods on an object after passing it to std::move. If the variable must be reused, assign a new value to it before the next use; any assignment, including operator=, reinitializes the moved-from state. Limit the scope of the variable so that its declaration is immediately followed by the move, leaving no room for accidental subsequent use. Use std::exchange when you need to transfer ownership and reset the source to a known value in one operation.

Vulnerable code example 1: method call on moved-from object

Copy
#include <string>
#include <utility>

void f() {
    std::string s = "hello";
    std::string t = std::move(s);   // s enters moved-from state
    std::size_t n = s.size();       // CERT.EXPR.MOVED_FROM.USE: 's' used after move
}

After std::move(s) is consumed by the move constructor of t, s is in a moved-from state. Calling s.size() reads an unspecified value. In practice most std::string implementations leave the moved-from string empty, but the standard does not guarantee this.

Vulnerable code example 2: moved-from object passed to free function

Copy
#include <string>
#include <utility>

void consume(std::string s);

void g() {
    std::string s = "hello";
    consume(std::move(s));   // s enters moved-from state
    consume(s);              // CERT.EXPR.MOVED_FROM.USE: 's' used after move
}

The first call transfers ownership of the string data; the second call copies from the moved-from s, whose value is unspecified.

Vulnerable code example 3: double move of a non-smart-pointer object

Copy
#include <string>
#include <utility>

void h() {
    std::string s = "hello";
    std::string t = std::move(s);   // s enters moved-from state
    std::string u = std::move(s);   // CERT.EXPR.MOVED_FROM.USE: 's' used after move
                                    // u contains an unspecified value — silent logic error
}

Unlike smart pointers (whose moved-from state is always nullptr), std::string and most other standard-library types have an unspecified moved-from value. Passing the moved-from s to a second std::move reads that unspecified value.

Fixed code example 1: do not use the object after the move

Copy
#include <string>
#include <utility>

void consume(std::string s);

void f() {
    std::string s = "hello";
    consume(std::move(s));   // s is not used after this point — compliant
}

Fixed code example 2: reinitialize before reuse

Copy
#include <string>
#include <utility>

void f() {
    std::string s = "hello";
    std::string t = std::move(s);   // s enters moved-from state
    s = "world";                    // reinitialize: assignment restores s
    std::size_t n = s.size();       // OK: s has a well-defined value again
}

External guidance