0

I am puzzled by the following code:

#include <iostream>

int main()
{
    int x{};

    int&& rvx = static_cast<int&&>(x);
    ++rvx;
    std::cout << x << std::endl;
}

The output of it is 1. I don't understand how this works. The static_cast is supposed to cast the lvalue x into an xvalue, which is then assigned to rvx. Why does incrementing rvx lead to a change in x? Is this because the converted lvalue-to-rvalue is essentially sitting at the same memory location, but it is just considered now a rvalue? I was under the impression (which is probably false) that somehow the cast creates a temporary out of its argument.

vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • I think you are mixed up about what *lvalue* and *rvalue* means. Those are adjectives that describe an expression. They are not varieties of objects. – M.M Feb 17 '15 at 22:20
  • There is no internal state of an integer, besides it's value (There is nothing to move). –  Feb 17 '15 at 22:22
  • @MattMcNabb I was a bit sloppy on my wording, I know that objects are always lvalues (as they are named), but as I said was under the impression that the static_cast makes a copy. – vsoftco Feb 17 '15 at 22:22
  • no, objects are not lvalues. They're objects. An lvalue is a category of expression. – M.M Feb 17 '15 at 22:23
  • @DieterLücking yes I know that writing `int x = std::move(y)` etc is non-sense. I was just confused with the cast. – vsoftco Feb 17 '15 at 22:23
  • @vsoftco Now I think you're confused between objects and variables. –  Feb 17 '15 at 22:23
  • @hvd, yes I am actually by the terminology – vsoftco Feb 17 '15 at 22:24
  • 1
    @vsoftco An object is a region of memory. There's also some bits about an object's type, but the important part, it's a region of memory. There's no notion of how you access that memory. It may be through a variable, or it may be through any other expression. The result of a succesful call to `malloc()` points to an object, or to a sequence of objects, even though there is no variable referring to those objects. –  Feb 17 '15 at 22:26
  • @hvd, ok, makes sense now. So basically `static_cast(x)` is just an expression denoting an object that happens to have the share the same memory with `x`, which is then bound to the lvalue `rvx` of type rvalue reference, am I right? – vsoftco Feb 17 '15 at 22:28
  • @MattMcNabb It is a C++-standard term. [basic] A *variable* is introduced by the declaration of a reference other than a non-static data member or of an object. The variable’s name denotes the reference or object. –  Feb 17 '15 at 22:29
  • @vsoftco `static_cast(x)` is not an object, it's an expression. An object is a region of storage, as hvd says. Expressions may or may not denote objects. Objects cannot share memory with other objects (except for sub-objects, e.g. array elements) – M.M Feb 17 '15 at 22:30
  • @hvd now that's a confusing sentence, I guess it is meant to be parsed as (the declaration of a reference other than...) or ([the declaration] of an object) – M.M Feb 17 '15 at 22:32
  • @MattMcNabb Indeed. Both that it's confusing, and that that's how it should be parsed. :) –  Feb 17 '15 at 22:32
  • OK, so variables can share storage, and we would say that `rvx` and `x` are both variables that denote the same object. – M.M Feb 17 '15 at 22:34
  • @vsoftco Pretty much. `static_cast(x)` is an expression that refers to the same object that `x` refers to (not just a different object at the same memory location, but really the same object), and that object is bound to `rvx`. –  Feb 17 '15 at 22:34
  • @MattMcNabb Indeed, that's a good way of putting it. –  Feb 17 '15 at 22:35
  • Ok, thanks all, I understand now what's going on. – vsoftco Feb 17 '15 at 22:36

2 Answers2

5

rvalue reference is a reference. In this, it works just like any other reference.

StenSoft
  • 9,369
  • 25
  • 30
4

An rvalue reference can bind to a temporary. This is what you'd get, for instance, if you write

int x{};
int&& rvx = +x;

But it doesn't need to bind to a temporary. By casting x to int&&, you've indicated to the compiler that that's okay too, that it may treat x as an rvalue to bind directly to the reference.