Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.52/64: Рейтинг темы: голосов - 64, средняя оценка - 4.52
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614

Зачем нужны rvalue ссылки, если есть универсальные ссылки

09.01.2017, 17:41. Показов 12617. Ответов 29
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Читаю книгу Скотта Мэйерса...
Что-то я совсем запутался с этими rvalue ссылками. Я не пойму, зачем нужны rvalue ссылки, если есть универсальные ссылки, который принимают на себя как rvalue, так и lvalue?
Пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class A
{
public:
    A() { std :: cout << "Constructor A" << std :: endl; p = 5; }
    ~A() { std :: cout << "Destructor A" << std :: endl; }
    
    int p;
};
 
void foo( A&& rvalue )
{
    rvalue.p = 7;
}
 
template<class T>
void foo2( T&& universalRef )
{
    universalRef.p = 7;
}
 
int main()
{
    A object;
    foo2( A() );    // нет ошибок rvalue
    foo2(object );    // нет ошибок lvalue
 
    foo( A() ); // нет ошибок rvalue
    foo(object ); // ошибка, нужно привести object к rvalue, тоесть std::move(object)
    
}
Я нихрена, извините конечно, не понимаю, зачем такое разделение нужно. Я вовсе затонул в этой лапше. Помогите пожалуйста понять, зачем все это нужно. Где применяется то, а где другое, в чем продуктивность одного метода реализации функции foo, а в чем другого.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.01.2017, 17:41
Ответы с готовыми решениями:

Не понял в С++ зачем нужны ссылки в функциях и Перегрузку конструктора!
Мож кто разьяснит в этих темам что и для чего они нужны!обяз с примерами!

Зачем нужны ссылки на методы?
Типа System.out.println()? Нет, конечно, я понимаю, что они позволяют сократить запись вида s -&gt; System.Out.println(s), но это как-то...

зачем нужны анонимус-функции? если есть {} и let
Часто вижу подобные куски кода ( function() { ... var a = 5; /// })(); undefined a VM186:1 Uncaught ReferenceError: a...

29
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
09.01.2017, 18:03
https://www.cyberforum.ru/blog... og826.html
http://stackoverflow.com/quest... d-prvalues
Дело в том, что тип T и тип universalRef это разные вещи. Шаблон может раскрыться с другим типом. Вроде бы у Майерса как раз понятнее всех это объяснено.
0
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
09.01.2017, 18:05
rvalue не тоже самое что универсальная ссылка. rvalue параметры в функциях явно указывают что переданный аргумент должен быть именно rvalue. Универсальная ссылка, напротив, может быть привязана как к rvalue так и к lvalue, а фактический параметр можно потом определить в теле функции с помощью std::forward
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
09.01.2017, 18:08  [ТС]
MrGluck,
Цитата Сообщение от MrGluck Посмотреть сообщение
Дело в том, что тип T и тип universalRef это разные вещи. Шаблон может раскрыться с другим типом.
это я тоже прекрасно понял. То что в функции тип universalRef имеет lvalue, но при использовании функции foo2 где-нибудь, я могу передать туда не только lvalue, но и rvalue, но так как universalRef в функции foo2 имеет тип lvalue, то она может потерять информацию о том, что я передавал rvalue. Так вот эта информация скрыта в T, и std::forward помогает мне это определить, при передаче universalRef дальше по стеку функций. Это все понятно. Мне непонятно зачем нужна функция foo, которая принимает на себя только rvalue. Зачем она нужна, если универсальные ссылки могут принимать как rvalue так и lvalue на себя
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
09.01.2017, 18:10
Цитата Сообщение от Bretbas Посмотреть сообщение
Мне непонятно зачем нужна функция foo, которая принимает на себя только rvalue.
Чтобы запретить принимать не rvalue. Например, потоки ввода-вывода или unique_ptr могут быть только перемещены, для них нужно явно писать move.
0
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
09.01.2017, 18:44
C++
1
2
3
void foo(A&& rvalue) //сюда можно передать только rvalue 
template<class T>
void foo2(T&& arg1, T&& arg2, T&& arg3) // передавайте сюда что хотите - если это будет rvalue, то я буду работать эффективнее, если lvalue - то как обычно
Добавлено через 13 минут
Bretbas, заметьте еще что функция с универсальной ссылкой может принять что угодно поскольку это шаблон, а функция с rvalue принимает только определенно заданный тип. С функциями, принимающими универсальные ссылки, могут возникнуть проблемы перегрузки с другими "нормальными" функциями.

Добавлено через 13 минут
Могут еще возникнуть проблемы с масштабируемостью и эффективностью при перегрузках двух схожих по функционалу функций - одна принимает lvalue, а другая rlavue. Но это долго объяснять (лутше почитать: стр. 177 переведенной книги Мейерса).

Добавлено через 5 минут
Плюс еще тема для ознакомления с проблемами перегрузки с универсальными ссылками: [дизайн и эволюция] провалы в variadic конструкторы
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
09.01.2017, 18:45  [ТС]
MrGluck,
Цитата Сообщение от MrGluck Посмотреть сообщение
Например, потоки ввода-вывода или unique_ptr могут быть только перемещены
Рази их нельзя передать просто по ссылке?
notAll,
C++
1
void foo2(T&& arg1, T&& arg2, T&& arg3) // передавайте сюда что хотите - если это будет rvalue, то я буду работать эффективнее
В чем эффективнее будет работать функция, если передавать rvalue. И почему?

Цитата Сообщение от notAll Посмотреть сообщение
заметьте еще что функция с универсальной ссылкой может принять что угодно поскольку это шаблон, а функция с rvalue принимает только определенно заданный тип. С функциями, принимающими универсальные ссылки, могут возникнуть проблемы перегрузки с другими "нормальными" функциями.
Это я все понял из книги Мэйерса Но все равно спасибо
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
09.01.2017, 19:03
Цитата Сообщение от Bretbas Посмотреть сообщение
Рази их нельзя передать просто по ссылке?
Имелось ввиду это:
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <memory>
#include <vector>
 
 
int main()
{
    std::unique_ptr<int> p = std::make_unique<int>(42);
    std::vector<std::unique_ptr<int>> v;
    // v.push_back(p); error
    v.push_back(std::move(p)); // OK
}
Добавлено через 4 минуты
Цитата Сообщение от Bretbas Посмотреть сообщение
В чем эффективнее будет работать функция, если передавать rvalue. И почему?
Вам нужно объяснить для чего придумали move семантику?
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
09.01.2017, 19:33
Цитата Сообщение от notAll Посмотреть сообщение
я буду работать эффективнее, если lvalue - то как обычно
Ну вы же понимаете, что это не всегда верно.
(да-да, базовые типы копируются быстрее, чем перемещаются.)
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
09.01.2017, 19:41  [ТС]
MrGluck,
Цитата Сообщение от MrGluck Посмотреть сообщение
Имелось ввиду это:
Я имел ввиду, зачем нужны rvalue, если я могу написать такую функцию foo, и она будет также работать как для lvalue так и для rvalue:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <memory>
#include <vector>
 
 void foo( const std::unique_ptr<int>& value )
 {
 }
 
int main()
{
    std::unique_ptr<int> p = std::make_unique<int>(42);
    std::vector<std::unique_ptr<int>> v;
    // v.push_back(p); error
    v.push_back(std::move(p)); // OK
    foo( p );
    foo(std :: move(p) );
}
Цитата Сообщение от MrGluck Посмотреть сообщение
Вам нужно объяснить для чего придумали move семантику?
Не стоит я думаю
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
09.01.2017, 19:56
Цитата Сообщение от GbaLog- Посмотреть сообщение
(да-да, базовые типы копируются быстрее, чем перемещаются.)
Можно сделать так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
 
template <typename T>
void foo(const T &)
{
    std::cout << "(const T &)\n";
}
 
template <typename T, typename std::enable_if<!std::is_copy_constructible<T>::value>::type * = 0>
void foo(T &&)
{
    std::cout << "(T &&)\n";
}
 
struct Bar
{
    Bar() = default;
    Bar(const Bar &) = delete;
};
 
int main()
{
    foo(int());
    foo(Bar());
}
1
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
09.01.2017, 19:59
Цитата Сообщение от MrGluck Посмотреть сообщение
Можно сделать так
Вы точно мне хотели ответить? Мой ответ заключался немного в другом.
P.S. Передача по ссылке тоже обычно дороже, чем по значению.
1
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,028
Записей в блоге: 1
09.01.2017, 20:10
Цитата Сообщение от Bretbas Посмотреть сообщение
Я не пойму, зачем нужны rvalue ссылки, если есть универсальные ссылки, который принимают на себя как rvalue, так и lvalue?
Потому что нет никаких универсальных ссылок.
Да даже у этого самого Майерса почитайте - он придумал термин для облегчения пояснения.
Универсальная ссылка - это сочетание двух факторов.
А именно, наличие rvalue-ссылки и вывода типа.
А далее в дело идет сворачивание ссылки, при необходимости.
Так что все эти универсальные ссылки невозможны без r/lvalue-ссылок,
точнее, универсальные ссылки - это и есть r/lvalue-ссылки.
Будет это rvalue-ссылка или lvalue-ссылка,
зависит от выведенного из аргумента типа.
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
09.01.2017, 20:14  [ТС]
MrGluck, Да можно сделать как угодно. У меня вопрос в другом. В чем разница этого всего? Теперь у меня еще один вопрос назрел, зачем универсальные ссылки нужны, если обычные ссылки, такие как void foo( const T& value ) принимают как и rvalue, так и lvalue. Я совсем запутался.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
 
 void foo( const int& value )
 {
 }
 
 template<class T>
 void foo2( T&& value )
 {
 }
 
int main()
{
    int p = 5;
    
    foo( p ); // lvalue (1)
    foo( std :: move( p ) ); // rvalue (2)
    foo2( p ); //lvalue (3)
    foo2( std :: move( p ) ); // rvalue (4)
}
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,028
Записей в блоге: 1
09.01.2017, 20:20
Цитата Сообщение от Bretbas Посмотреть сообщение
зачем универсальные ссылки нужны
например, для эффективного использования аргументов функции.
Цитата Сообщение от Bretbas Посмотреть сообщение
Я совсем запутался.
Это всё потому, что Вы не разобрались с использованием r/lvalue ссылок.
Забудьте о всяких универсальных ссылках, разберитесь с базовыми вещами.
Цитата Сообщение от Bretbas Посмотреть сообщение
такие как void foo( const T& value )
И как внутри узнать, можно захапать объект или нет?
C++
1
2
3
4
 template<class T>
 void foo2( T&& value )
 {
 }
А теперь возьмем множество параметров:
C++
1
2
3
4
 template<class ... Args>
 void foo2( Args &&... value )
 {
 }
предлагаете сделать бесконечное число вариантов с комбинациями r/lvalue ссылок?
1
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
09.01.2017, 20:27
Кстати да, Croessmah прав, по идее и нет никаких универсальных ссылок, всё дело в свёртывании ссылок.
C++
1
2
3
4
5
6
7
8
9
10
11
/////////////////////////////////////////////////////////////////////////////////////////
template<typename Tp>
void foo(Tp&&)
{}
/////////////////////////////////////////////////////////////////////////////////////////
int main()
{
    int n;
    foo(n); // в foo Tp == int& &&(о боже, ссылка на ссылку!!! убрать срочно!!!) -> Tp == int& -> lvalue
    foo(int{}); // в foo Tp == int&& -> rvalue
}
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,028
Записей в блоге: 1
09.01.2017, 20:28
Не знаю, может поможет:
Нюансы синтаксиса: где, как и для чего используется &&
Семантика перемещения и perfect forwarding(правильная передача)
Что значат два амперсанда?
Std::move
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
09.01.2017, 20:29  [ТС]
Croessmah,
Цитата Сообщение от Croessmah Посмотреть сообщение
И как внутри узнать, можно захапать объект или нет?
В плане захапать? ну через std :: forward. Вроде она должна приведение сделать относительно того что я передал в void foo( const T& value )
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,028
Записей в блоге: 1
09.01.2017, 20:31
Bretbas, у Вас явно всё перепуталось.
std::forward в void foo( const T& value ) бесполезен.
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
09.01.2017, 20:35  [ТС]
Croessmah,
Цитата Сообщение от Croessmah Посмотреть сообщение
std::forward в void foo( const T& value ) бесполезен.
ааааааа!!У меня мозг взорвется сейчас. Почему бесполезен?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
09.01.2017, 20:35
Помогаю со студенческими работами здесь

Зачем нужны массивы, если есть обычные переменные?
Здравствуйте. У меня есть вопрос. Зачем нужны массивы, если есть обычные переменные? Можно ведь написать не так: int a= {6,5}; а так:...

А зачем нужны веб программисты, если есть wordpress?
Открыл я сайт с вакансиями, а там написано &quot;требуется программист php, зарплата 90 тыс в месяц&quot;. Звоню спрашиваю, что вы пишете..они...

Зачем нужны наборы в Evernote, если есть Блокноты?
Зачем нужны наборы в Evernote, если есть Блокноты?

Зачем нужны модули, если есть пространства имён?
Зачем нужны модули, если есть пространства имён?

Зачем нужны обычные массивы, если есть динамические?
Всем привет! Вопрос в заголовке. Если динамический массив даёт те же и ещё больше функций и, при том, лучше обращается с памятью, зачем...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG-файла с альфа-каналом с помощью библиотеки SDL3_image на Android
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru