Перехожу в одиннадцатый стандарт из старого и в нем много нового для меня, в частности не понятно для чего в параметрах функций пишут двойной амперсанд &&. Неясно для чего он нужен и как его можно использовать?
Вот небольшой примерчик:
void test(int && a){
a++;
// как работать с таким параметром (а) внутри функции, например вывести ее на экран?
}
int main(){
int a = 1;
test(a); // как передать переменную?
return 0;
}
Ответ
Пока читаете, для себя такое небольшое правило выработал:
type& - аргумент обязательно lvalue, т.е. то, что стоит слева от знака равно:
int a = 1;
foo(a); // a может быть изменено в foo и по выходу иметь другое значение
foo(1); // ошибка компиляции
const type& - аргумент может быть как lvalue (при этом даёте гарантию, что он там не поменяется) или rvalue, тогда его время жизни продлевается на время вызова:
int a = 1;
bar(a); // а не меняется внутри
bar(2); // тоже легально
type&& - аргумент может быть только rvalue, при этом внутри вызова можно его изменять и вообще, работаете как с обычной переменной (как только rvalue внутри функции обретает имя, оно "автоматом" становится lvalue :-)). Чтобы обычную переменную превратить в rvalue, нужно её "переместить", т.е. по сути, отдать владение в вызываемую функцию:
int a = 1;
baz(a); // ошибка компиляции
baz(std::move(a)); // всё отлично, но после вызова состояние a не определено.
baz(2); // тоже отлично, 2 - rvalue
const type&& - такая конструкция возможна, но её смысл для меня ускальзывает. Она сродни такому:
void some(const int arg);
т.е. просто внутри менять запрещаете.
Из правил вытекает использование: когда нужно отдать владение объектом. Возможна просто дополнительная перегрузка, чтобы можно было работать в одинаковом стиле в вызывающем коде как с rvalue, так и lvalue:
void foo(int& a); // [1]
void foo(int&& a); // [2]
...
int a = 1;
foo(a); // вызовется [1]
foo(1); // вызовется [2]
foo(move(a)); // вызовется [2], состояние 'a' будет неопределено.
Комментариев нет:
Отправить комментарий