Logo
Articles Compilers Libraries Books MiniBooklets Assembly C++ Linux CPU Others Videos
Advertisement

Article by Ayman Alheraki on February 4 2026 09:32 AM

Why glvalue, xvalue, and prvalue Still Feel Confusing (and How the Rule of Five Makes Them Click)

Why glvalue, xvalue, and prvalue Still Feel Confusing (and How the Rule of Five Makes Them Click)

Many C++ developers can correctly define lvalue, rvalue, glvalue, xvalue, and prvalue. Yet when it’s time to apply the Rule of Three or Rule of Five in real code, something still feels off.

That feeling is valid.

The standard’s value categories are precise, but they are also descriptive, not instructional. They tell you what an expression is, but they don’t automatically tell you what you should do about ownership, copying, or moving.

This article connects the theory to the part that matters in production C++: identity and ownership transitions.

The one practical question that unlocks everything

Instead of memorizing tables, ask one question:

Does this expression represent a reusable object (identity), or a disposable payload?

In modern C++ (RAII + Rule of Five), this is the real axis behind the categories.

glvalue: “This has identity”

A glvalue refers to something that has identity: it exists somewhere in memory and you can refer to it again.

Typical glvalues:

  • named variables

  • class members

  • dereferenced pointers

  • references

If it has identity, it can be used again later. That fact alone explains why copying exists as a meaningful operation.

lvalue: “Reusable identity”

An lvalue is a glvalue that represents a reusable object. It’s stable. You’re not expected to take it apart.

Practical meaning:

  • the caller likely still needs s

  • copying is the safe default

  • moving requires explicit permission

That’s why copy constructors and copy assignment exist: they support the “reusable object” path.

xvalue: “Identity marked as disposable”

This is where confusion tends to accumulate.

An xvalue still has identity, but you have explicitly marked it as disposable—most commonly with std::move.

What this really means:

“This object still exists, but I promise I won’t use its old value again.”

That promise is the moral and technical basis for move semantics. A move constructor is not “magic performance.” It is an ownership transfer that is only correct because the source is allowed to become “valid but unspecified.”

prvalue: “Pure temporary payload”

A prvalue is a pure temporary result. It has no identity of its own in the way a named variable does.

Practical meaning:

  • there is no “old object” to preserve

  • it’s a payload meant to build a new object

Since C++17, prvalues are even more important: in many cases they do not materialize a separate temporary object at all; instead, the final object is constructed directly when needed. This is why return-by-value is typically efficient and not something you should fear.

The Rule of Five is not really about value categories. It’s about resource ownership and transitions.

If your class owns a resource (memory, file handle, socket, mutex, OS object), you must answer four questions:

  1. What happens when I copy from a reusable object?

  2. What happens when I move from a disposable object?

  3. What happens when I assign over an existing object?

  4. What happens when the object dies?

Value categories simply tell you which scenario you’re in.

Here is the practical mapping:

  • lvalue → the source is reusable → copy

  • xvalue → the source is disposable → move

  • prvalue → temporary payload → construct

  • destruction → release owned resource

A minimal RAII example (where it truly clicks)

Read it with the identity lens:

  • Copy constructor: “You might still need yours, so I duplicate.”

  • Move constructor: “You said you’re done with it, so I steal.”

  • Destructor: “I release what I own.”

This is why value categories matter: they decide whether stealing is legal.

How professionals actually think

Most experienced C++ developers don’t actively think:

“Is this a glvalue or prvalue?”

They think:

Am I allowed to steal from this?

  • If yes → move

  • If no → copy

  • If new → construct

That mental model matches both modern C++ style and how compilers optimize.

Final takeaway

Value categories stop being confusing when you stop treating them as vocabulary and start treating them as ownership signals.

  • lvalue means “reusable object” → copy is expected

  • xvalue means “disposable identity” → move is allowed

  • prvalue means “temporary payload” → construct directly

Once you see them this way, the Rule of Five stops feeling like a rule—and starts feeling like simple resource logic.

Advertisements

Responsive Counter
General Counter
1046923
Daily Counter
559