c++ – The ubiquitous use of r-value links

Question:

Should you try to use r-value links as often as possible everywhere? Here's the code:

std::string hi() {
    return "hello world\n"
}

auto&& str = hi();

In this case, on line 5, there is only one object creation, and the r-value is a reference to it, and no copying … effectively if you compare, for example, with:

auto str = hi();

or

auto str = std::move(hi());

Therefore, at first glance, the conclusion suggests itself: why not create r-value links as often as possible instead of the usual variable initialization? Especially if you need to create these variables 100,000 times per second. Suppose, if possible, then write like this:

void function() {
    int&& a = 1;
    double&& b = 2.;
    auto&& value = return_value();
    /*далее какой-то код*/
}

and then work with these links or pass them to another place … it looks, this is a little more monstrous than the usual initialization of variables, to which the eye is accustomed:

void function() {
    int a = 1;
    double b = 2.;
    auto value = return_value();
    /*далее какой-то код*/
}

Therefore, is it worth using r-value references as often as possible instead of the usual initialization of new variables in a local context (inside functions, for example) for efficiency, or are there any built-in optimizations that, when int a = 2 do the same actions as int&& a = 2 ?

Answer:

In fact, accessing a variable directly is always faster than accessing it by reference. Let's create a simple program:

int O() {
    int x = 5;
    return x;
}

int test(){
  auto&& value = O();
  return value;
}

int test2(){
   auto value = O();
  return value;
}

Let's collect WITHOUT optimizations.

test():
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        call    O()
        mov     DWORD PTR [rbp-12], eax
        lea     rax, [rbp-12]
        mov     QWORD PTR [rbp-8], rax
        mov     rax, QWORD PTR [rbp-8]
        mov     eax, DWORD PTR [rax]
        leave
        ret
test2():
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        call    O()
        mov     DWORD PTR [rbp-4], eax
        mov     eax, DWORD PTR [rbp-4]
        leave
        ret

As you can see, the work is direct – there are fewer operations at once, although we did not use the variable count. In general, for primitives, a variable is definitely better, for complex classes – use a profiler (perhaps it makes sense to use a move constructor or something like that).

Scroll to Top