what does const rvalue mean?

Hi, i can understand the term lvalue,const lvalue, lvalue reference,const lvalue reference,rvalue, rvalue reference and const rvalue reference, but i can't understand the term const rvalue.

what does const rvalue mean? and how to get a const rvalue?

For example:

int i = 5,j = 3;
i+j;

what is 5? a rvalue or a const rvalue?
what is i+j? a rvalue or a const rvalue?

when i define i from 5, 5 is copied to i or moved to i?

Thank you in advance
> what is 5? a rvalue or a const rvalue?

It is an expression that has a type and a value category.

(5) type: int value category: prvalue (pure rvalue)

int i = 5 ; const int j = 3; i+j type: int value category: prvalue (pure rvalue)
(i) type: int value category: lvalue
(j) type: const int value category: lvalue


> when i define i from 5, 5 is copied to i or moved to i?

int is a scalar type; scalars and other POD types are trivially moveable.
There is no difference between move and copy for such types.


> what does const rvalue mean?

The primary value categories correspond to two properties of expressions:

has identity: it's possible to determine whether the expression refers to the same entity as another expression, such as by comparing addresses of the objects or the functions they identify (obtained directly or indirectly);

can be moved from: move constructor, move assignment operator, or another function overload that implements move semantics can bind to the expression.

Expressions that:
.... have identity and cannot be moved from are called lvalue expressions;
.... have identity and can be moved from are called xvalue expressions;
.... do not have identity and can be moved from are called prvalue expressions;
.... do not have identity and cannot be moved from are not used.

http://en.cppreference.com/w/cpp/language/value_category
int i = 5, j = 3;
In the above 5 and 3 are constants that are rvalues, i and j are lvalues.

i+j;
What are you trying to do here? This is an invalid statement. Perhaps you meant something like:

int k = i + j;

Here k is an lvalue, the result of the calculation (i + j) is an rvalue.

> i+j; This is an invalid statement.

The statement has no effect; nevertheless it is well-formed.

It is an expression statement; the expression is a discarded-value expression.
Note: "An expression statement with the expression missing is called a null statement" - IS
rvalue expressions of class type may be const. It means that a non-const member function cannot be called on such an expression, and that a non-const rvalue reference cannot be bound to it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
struct S {
    void const_f() const { std::cout << "const_f\n"; }
    void non_const_f() { std::cout << "non_const_f\n"; }
};
const S getAConstRV() { return S{}; }
int main()
{
    getAConstRV().const_f(); // OK
//  getAConstRV().non_const_f(); // Error

    const S&& r1 = getAConstRV(); // OK
//  S&& r2 = getAConstRV(); // Error
}


scalar rvalues are never const: a function declared const int f(); has type const int(), but the type of the function call expression f() is int, and f() will bind to int&&.


PS: updated that move-from/has-identity explanation of value categories with a footnote; the standard calls T(const T&&) a "move contsructor" too, and that binds const prvalues, even if it's rather useless.
Last edited on
i appreciate all your comments

@Cubbi Thank you very much for your example which really helps to understand. and i verified the difference between const rvalue expressions of class type and built-in type using the code below
so, f() returns a const int, but can bind to int &&, g() returns a const string, and the return CANNOT bind to string &&.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<string>

const int f()
{
    return 3;
}

const std::string g()
{
    return "hello";
}

int main()
{
    int &&i1 = f();
    const &&i2 = f();
    const std::string &&s1 = g();
    std::string &&s2 = g();    //  error
    std::cout<<i1<<'\n';       // 3
    std::cout<<i2<<'\n';       // 3
    std::cout<<s1<<'\n';      // hello
    std::cout<<s2<<'\n';      // error
}


@JLBorges Thank you for the website link and your elaborative explanation. and thank you @jlb
Topic archived. No new replies allowed.