c++ – What does double ampersand (&&) mean in function parameters and how do I use it?

Question:

I am switching to the eleventh standard from the old one and it contains a lot of new things for me, in particular, it is not clear why the double ampersand && is written in the function parameters. Unclear what it is for and how can it be used?

Here's a quick example:

void test(int && a){
    a++;
    // как работать с таким параметром (а) внутри функции, например вывести ее на экран?
}

int main(){
    int a = 1;

    test(a); // как передать переменную?

     return 0;
}

Answer:

While you are reading, I have developed such a small rule for myself:

  1. type& – the argument is required lvalue, i.e. what is to the left of the equals sign:

     int a = 1; foo(a); // a может быть изменено в foo и по выходу иметь другое значение foo(1); // ошибка компиляции
  2. const type& – the argument can be either an lvalue (at the same time you give a guarantee that it will not change there) or an rvalue, then its lifetime is extended for the duration of the call:

     int a = 1; bar(a); // а не меняется внутри bar(2); // тоже легально
  3. type&& – the argument can only be an rvalue, while inside the call you can change it and, in general, work as with a regular variable (as soon as an rvalue inside a function acquires a name, it automatically becomes an lvalue :-)). To turn an ordinary variable into an rvalue, you need to "move" it, i.e. in essence, to give ownership to the called function:

     int a = 1; baz(a); // ошибка компиляции baz(std::move(a)); // всё отлично, но после вызова состояние a не определено. baz(2); // тоже отлично, 2 - rvalue
  4. const type&& – such a construction is possible, but its meaning is slipping away for me. She is akin to this:

     void some(const int arg);

    those. just forbid to change inside.

From the rules follows the use: when you need to give ownership of an object. Just an additional overload is possible so that you can work in the same style in the calling code with both rvalues ​​and lvalues:

void foo(int& a);  // [1]
void foo(int&& a); // [2]
...
int a = 1;
foo(a); // вызовется [1]
foo(1); // вызовется [2]
foo(move(a)); // вызовется [2], состояние 'a' будет неопределено.
Scroll to Top