С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.73/37: Рейтинг темы: голосов - 37, средняя оценка - 4.73
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
1

rvalue ссылки

17.12.2019, 11:36. Показов 7087. Ответов 93
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Может кто объяснить зачем нужны rvalue ссылки и как правильно работать с std::move и std::forward?
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.12.2019, 11:36
Ответы с готовыми решениями:

Зачем нужны rvalue ссылки, если есть универсальные ссылки
Читаю книгу Скотта Мэйерса... Что-то я совсем запутался с этими rvalue ссылками. Я не пойму, зачем...

Ссылки от rvalue
Доброго времени суток, господа! Начал читать статью про rvalue ссылки на хабре и что-то много...

Rvalue ссылки
Литературу читаю, но доезжаю медленно(если знаете где доступно описано- напишите),тяжело болею...

Rvalue и lvalue ссылки
Здравствуйте, что расскажите, пожалуйста что такое lvalue и rvalue ссылки и с чем их едят, где...

93
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.12.2019, 12:43 61
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от DrOffset Посмотреть сообщение
Может ты не будешь мне мешать учить человека, а
а ты уточняй, какой именно конструктор ты имеешь ввиду.
потому что их там два.

первый - обычный конструктор копирования,
участвуют в строительстве временного объекта.

второй - референсный.
используется при строительстве результирующиего объекта.

и когда ты пишешь:
Цитата Сообщение от DrOffset Посмотреть сообщение
Почему конструктор копирования (который есть у auto_ptr) не подходит в этом случае?
сразу возникает резонный вопрос:
почему же не подходит? подходит.
и подходит, и используется.

https://rextester.com/SMMF10447
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
18.12.2019, 12:43 62
Цитата Сообщение от ReYalp Посмотреть сообщение
насколько я понял то func возвращает rvalue? а конструктор принимает на вход lvalue?
Правильно. Поэтому рассматриваться начинает следующий вариант.
А там есть еще один конструктор который выглядит так:
C++
1
2
3
4
    auto_ptr(auto_ptr_ref<_Ty> _Right) noexcept
    {   // construct by assuming pointer from _Right auto_ptr_ref
//......
    }
А теперь вот у вашего вопроса
Цитата Сообщение от ReYalp Посмотреть сообщение
откуда берется вызов operator auto_ptr_ref<_Other>() noexcept я не понимаю и почему именно auto_ptr_ref
ответ на поверхности.
0
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
18.12.2019, 12:47  [ТС] 63
DrOffset, после прочтения главы мне должно стать понятно почему тут вызывается оператор ?

Добавлено через 2 минуты
DrOffset, просто слегка непонятно какую связь имеет operator auto_ptr_ref<_Other>() и rvalue ссылки ,почему вызывается именно он?
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
18.12.2019, 12:52 64
Цитата Сообщение от hoggy Посмотреть сообщение
а ты уточняй, какой именно конструктор ты имеешь ввиду.
Цитата Сообщение от hoggy Посмотреть сообщение
используется при строительстве результирующиего объекта.
Все уточнено. Процитирован участок кода, который рассматривается: инициализация объекта p1.

Добавлено через 4 минуты
Цитата Сообщение от ReYalp Посмотреть сообщение
после прочтения главы мне должно стать понятно почему тут вызывается оператор ?
После прочтения главы вам станет понятно почему тот конструктор не подошел.

Цитата Сообщение от ReYalp Посмотреть сообщение
просто слегка непонятно какую связь имеет operator auto_ptr_ref<_Other>() и rvalue ссылки
Вы сейчас находитесь в процессе нарабатывания базы знаний о предмете.

Про rvalue ссылки пока сейчас не думайте.

Цитата Сообщение от ReYalp Посмотреть сообщение
почему вызывается именно он?
Он вызывается, потому что конструктор копирования не подошел.
Потому что в классе есть другой конструктор, который принимает auto_ptr_ref<_Ty> и преобразование к auto_ptr_ref<_Other> (где _Other = _Ty) это единственный способ скомпилировать этот код.
0
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
18.12.2019, 12:55  [ТС] 65
DrOffset, насколько я понял то во время
C++
1
p1 = func<int>();
срабатывает что-то типа каста и func() с rvalue кастуется в lvalue? это что-то похожее на преобразование типов при инициализации?

Добавлено через 2 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
Он вызывается, потому что конструктор копирования не подошел.
просто впервые вижу такой опертор и мне не ясно как его вообще вызывать.
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
18.12.2019, 12:59 66
Цитата Сообщение от ReYalp Посмотреть сообщение
просто впервые вижу такой опертор и мне не ясно как его вообще вызывать.
Ну так это вопрос к вашим знаниям базового С++. Если вы встречаете непонятные побочные вопросы, то нужно остановиться, разобраться в них, потом вернуться к этой теме. Я же не зря вам про неделю на разбор сказал.
0
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
18.12.2019, 13:01  [ТС] 67
DrOffset, окей, Вы не подскажете как вызвать подобный оператор?
C++
1
2
3
4
5
6
7
8
9
10
template<class A>
class test {
 
public:
        template<class AA>
    operator test<AA>() {
        int a = 5;
    }
 
};
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
18.12.2019, 13:07 68
Цитата Сообщение от ReYalp Посмотреть сообщение
срабатывает что-то типа каста и func() с rvalue кастуется в lvalue?
Каст действительно есть. Оператор auto_ptr_ref<_Other> добавляет возможность неявного преобразования auto_ptr в auto_ptr_ref в подходящих для этого выражениях.

из-за того, что
* у нас конструктор копирования принимает lvalue-ссылку
* и в наличии другой конструктор, который принимает auto_ptr_ref по значению,
у нас созданы такие условия, когда инициализация объекта выражением rvalue подходит для использования этого неявного каста.

Добавлено через 1 минуту
Цитата Сообщение от ReYalp Посмотреть сообщение
Вы не подскажете как вызвать подобный оператор?
C++
1
2
3
    test<int> a;
    
    test<double> b = a;
Только возвращаемое значение укажите
C++
1
2
3
4
5
    template<class AA>
    operator test<AA>() {
        int a = 5;
        return test<AA>();
    }
0
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
18.12.2019, 13:29  [ТС] 69
DrOffset, тоесть
C++
1
auto_ptr<int> p1 =
в auto_ptr<int> p1 = func<int>() это и есть вызов этого опертора для rvalue объекта который возвращает func?
Я слегка запутался
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
18.12.2019, 13:48 70
Лучший ответ Сообщение было отмечено ReYalp как решение

Решение

Цитата Сообщение от ReYalp Посмотреть сообщение
это и есть вызов этого опертора для rvalue объекта который возвращает func?
Да.

Он вызывается потому что есть такой конструктор, который может принять auto_ptr_ref и потому что конструктор копирования не подходит. Т.е. два критерия.

Вы уже собственно увидели одно из главных недостатков этого: это запутывает.

Первая проблема (я надеюсь вы ее увидели, потому что ничего об этом не сказали и не спросили). Когда мы делаем инициализации p1 lvalue-объектом у нас срабатывает конструктор копирования. Но при этом у нас не происходит копирования. У нас происходит перемещение владения указателем из объекта p в объект p1. Т.е. по семантике мы делаем копирование, а по факту - перемещение. Это плохо тем, что запутывает читающего код.

Вторая проблема: когда у нас копирование может быть безопасно заменено на перемещение? Правильно, когда объект временный и данные ему все равно уже не нужны. Но тут старая редакция С++ вставляет палки в колеса. У нас нет возможности так просто отобрать владение у временного объекта. К lvalue-ссылке он не привязывается, а через константную ссылку объект не изменить (ну всякие хаки с конст_кастами и mutable оставим за скобками). Поэтому рождается вот такой запутанный код.
Итак в этом коде - конструктор от аргумента auto_ptr_ref - это прото-(в археологическом смысле)-конструктор перемещения. Сам auto_ptr_ref - это прото-rvalue-ссылка.

Собственно ответ на первы вопрос:
Цитата Сообщение от ReYalp Посмотреть сообщение
Может кто объяснить зачем нужны rvalue ссылки
rvalue ссылки нужны, чтобы со стороны ядра языка узаконить возможность отбирать ресурс у временных объектов. Чтобы делать это в строго определенных случаях, общее название которым move-семантика, т.е. семантика, в противоположность семантике копирования, которая явно предполагает наличие перемещения ресурса от объекта к объекту.

Цитата Сообщение от ReYalp Посмотреть сообщение
как правильно работать с std::move
std::move - это способ явно указать, что мы собираемся отобрать владение ресурсом у lvalue. Т.е. первый пример на предыдущей странице, когда p1 инициализуется p и вопрос по поводу состояния p получает явный ответ. И в коде становится заметно, что здесь у нас семантика перемещения, а не копирования.
1
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
18.12.2019, 14:00  [ТС] 71
DrOffset, у меня появилась проблема ,я не могу отобразить работу данной ситуации в более простом примере ,помогите пожалуйста ,что нужно поменять\дописать?
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
template<class A>
class test {
 
public:
    test() {};
    test(const test<A>& obj) {
    }
    template<class AA>
    operator test<AA>() {
        return test<AA>();
    }
};
 
template<class T>
test<T> func1() {
    test<T> p1;
    return p1;
}
 
 
int main()
{
    //auto_ptr<int> p1 = func<int>();
 
    test<int> a;
    test<double> b = func1<int>();
    system("pause");
}
почему в данном случае operator test срабатывает для объекта b ?

Добавлено через 2 минуты
hoggy,
Цитата Сообщение от hoggy Посмотреть сообщение
словно бык на красную тряпку.
доказано что быки не реагируют на красный как-то особенно и DrOffset просто учит меня(а в теории всех кто будет это читать) чему-то новому и тот вопрос который он мне задал был вопросом лично для меня ,так что извините если Вы не так что-то поняли
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
18.12.2019, 14:11 72
Цитата Сообщение от ReYalp Посмотреть сообщение
почему в данном случае operator test срабатывает для объекта b ?
Потому что у нас разные типы в шаблоне.
Получаем тип test<double> и тип test<int>.

Если между ними попробовать провести копирование, то ничего не выйдет. Это два разных типа, они не умеют копироваться друг в друга.

Но, если мы напишем пользовательский оператор преобразования, то это станет возможным.
Когда мы пишем
C++
1
2
3
4
    template<class AA>
    operator test<AA>() {
        return test<AA>();
    }
То читать это надо так: "определи возможность преобразования в тип test<AA>, где AA - любой тип."
Таким образом, если вы мысленно подставите вместо AA=double, то получите test<double> - это то, что у нас с левой стороны.
Компилятор делает тоже самое. Он видит тип с левой стороны - test<double>, видит оператор преобразования в test<AA>, подставляет AA=double, и получает успешную подстановку. Код компилируется.
0
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
18.12.2019, 14:18  [ТС] 73
DrOffset, у меня много вопросов 1. Если брать мой код то почему перед выховод оператора не срабатывает конструктор b? 2. Оператор возвращает значения но оно получается что никуда не приравнивается?
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
18.12.2019, 14:24 74
Цитата Сообщение от ReYalp Посмотреть сообщение
1. Если брать мой код то почему перед выховод оператора не срабатывает конструктор b?
Конструктор копирования b не срабатывает, потому что срабатывает RVO.
Вот тут я отключил это:
https://rextester.com/TJQVM58449
Можно увидеть, что делается по семантике (с++14).

Цитата Сообщение от ReYalp Посмотреть сообщение
2. Оператор возвращает значения но оно получается что никуда не приравнивается?
Из-за RVO-оптимизации, это значение сразу становится значением b.
0
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
18.12.2019, 14:40  [ТС] 75
DrOffset, можете объяснить как это работает?
если убрать std::endl в операторе и в func то в операторе a будет иметь непонятное значение,если добавить << std::endl то все ок?
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
31
32
33
34
35
36
37
//clang 3.8.0
 
#include <iostream>
 
template<class A>
class test {
 
public:
    test() {
        std::cout << __PRETTY_FUNCTION__ << " default ctor\n";
    }
    test(const test<A>& obj) {
        std::cout << __PRETTY_FUNCTION__ << " copy ctor\n";
    }
    template<class AA>
    operator test<AA>() {
        std::cout << this->a<< std::endl;
        std::cout << __PRETTY_FUNCTION__ << "\n";
        return test<AA>();
    }
    int a = 0;
};
 
template<class T>
test<T>& func1() {
    test<T> p1;
    p1.a = 25;
    std::cout << p1.a<< std::endl;
    return p1;
}
 
 
int main()
{
    test<int> a;
    test<double> b = func1<int>();
}
0
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
18.12.2019, 14:52  [ТС] 76
DrOffset, почему в таком случае не срабатывает оператор , а срабатывает конструктор?
Кликните здесь для просмотра всего текста
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
31
32
33
//clang 3.8.0
 
#include <iostream>
 
template<class A>
class test {
 
public:
    test() {
        std::cout << __PRETTY_FUNCTION__ << " default ctor\n";
    }
    test(const test<A>& obj) {
        std::cout << __PRETTY_FUNCTION__ << " copy ctor\n";
    }
    operator test<A>() {
        std::cout << this->a<<std::endl;
        std::cout << __PRETTY_FUNCTION__ << "\n";
        return test<A>();
    }
    int a = 0;
};
 
template<class T>
test<T> func1() {
    test<T> p1;
    return p1;
}
 
 
int main()
{
    test<int> b = func1<int>();
}
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.12.2019, 14:56 77
Цитата Сообщение от ReYalp Посмотреть сообщение
почему в таком случае не срабатывает оператор , а срабатывает конструктор?
потому что незачем.
в этом примере он вообще никак не используется.

убери его - результат не измениться.


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
31
32
33
34
#include <iostream>
 
template<class A>
class test {
 
public:
    test() {
        std::cout << __PRETTY_FUNCTION__ << " default ctor\n";
    }
    test(const test<A>& obj) {
        std::cout << __PRETTY_FUNCTION__ << " copy ctor\n";
    }
    #if 0
    operator test<A>() {
        std::cout << this->a<<std::endl;
        std::cout << __PRETTY_FUNCTION__ << "\n";
        return test<A>();
    }
    #endif
    
    int a = 0;
};
 
template<class T>
test<T> func1() {
    test<T> p1;
    return p1;
}
 
 
int main()
{
    test<int> b = func1<int>();
}
0
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
18.12.2019, 15:04  [ТС] 78
hoggy, та я понимаю что он не используется ,вот и спрашиваю почему

Добавлено через 3 минуты
если взять данный пример то зачем такой оператор нужен? И как его вызвать
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.12.2019, 15:07 79
Цитата Сообщение от ReYalp Посмотреть сообщение
та я понимаю что он не используется ,вот и спрашиваю почему
потому что не нужен, Карл!
ты же не используешь форточку, если тебе в принципе не нужно открывать окошко.

Цитата Сообщение от ReYalp Посмотреть сообщение
если взять данный пример то зачем такой оператор нужен?
правильный вопрос звучит так:
зачем вообще нужен пользовательский оператор приведения?
в каких случаях, и для каких целей он используется?
1
63 / 46 / 11
Регистрация: 27.12.2017
Сообщений: 1,484
18.12.2019, 15:14  [ТС] 80
hoggy, вот , если взять такой пример
C++
1
2
3
4
5
struct Widget {
  Widget(int) {}
};
 
Widget w1 = 1;
то чтобы этот код(без оптимизации ) отработал правильно нужен такой оператор в int ?
Но почему это работает и в случае конструктора в Widget(int)?

Добавлено через 59 секунд
если я правильно понял то существует тогда 2 варианта преобразование типов ? С помощью конструкторов и операторов ? Или как
0
18.12.2019, 15:14
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
18.12.2019, 15:14
Помогаю со студенческими работами здесь

STL и rvalue ссылки
Привет. Помню как-то читал инфу о том, что в стандартных контейнерах rvalue работают, как lvalue....

RVALUE ссылки и операции с ними
Господа знатоки у меня вопрос следующий. Увидел недавно такую запись &quot;T&amp;&amp; a&quot;, узнал что это rvalue...

Запретить initializer-list конструктору принимать rvalue значения/ссылки
Здравствуйте! Опишу проблему из заголовка поста на примере... Допустим есть шаблонный класс с...

Ссылка на rvalue, является ли она сама rvalue?
А верно ли, что ссылка на rvalue сама не является rvalue? Вот такой код является валидным: #include...


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

Или воспользуйтесь поиском по форуму:
80
Закрытая тема Создать тему
Новые блоги и статьи
Как написать микросервис на Go/Golang с Kafka и GitHub CI/CD
InfoMaster 14.01.2025
Определение микросервиса, преимущества использования Go/ Golang Микросервис – это архитектурный подход к разработке программного обеспечения, при котором приложение состоит из небольших, независимо. . .
Как написать микросервис с нуля на C# с RabbitMQ, CQRS и CI/CD
InfoMaster 14.01.2025
В современном мире разработки программного обеспечения микросервисная архитектура стала стандартом де-факто для создания масштабируемых и гибких приложений. Этот архитектурный подход предполагает. . .
Как создать интернет-магазин на PHP и JavaScript
InfoMaster 14.01.2025
В современном мире электронная коммерция стала неотъемлемой частью бизнеса. Создание собственного интернет-магазина открывает широкие возможности для предпринимателей, позволяя достичь большей. . .
Как написать Тетрис на Ассемблере
InfoMaster 14.01.2025
Тетрис – одна из самых узнаваемых и популярных компьютерных игр, созданная в 1984 году советским программистом Алексеем Пажитновым. За прошедшие десятилетия она завоевала симпатии миллионы людей по. . .
Как создать игру "Танчики" на Unity3d и C#
InfoMaster 14.01.2025
Разработка игр – это увлекательный процесс, сочетающий в себе творчество и технические навыки. В этой статье мы рассмотрим создание классической игры "Танчики" с использованием Unity3D и языка. . .
Организую платный онлайн микро-курс по доработке Android-клиента Telegram
_Ivana 14.01.2025
Официальная версия и распространенные форки не полностью устраивают? Сделай свою кастомную версию клиента! 4 занятия по 2 часа (2 недели пн, ср 19:00-21:00 по Москве). Первое вводное занятие. . .
Как создать приложение для фитнеса для iOS/iPhone на Kotlin
InfoMaster 14.01.2025
Создание собственного фитнес-приложения — это не только захватывающий, но и полезный процесс, ведь оно может стать вашим верным помощником на пути к здоровому и активному образу жизни. В современных. . .
Как создать приложение магазина для iOS/iPhone на Swift
InfoMaster 14.01.2025
Введение в разработку iOS-приложений Разработка приложений для iPhone и других устройств на базе iOS открывает огромные возможности для создания инновационных мобильных решений. В данной статье мы. . .
Это работает. Скорость асинхронной логики велика. Вопрос видимо останется в стабильности. Плата - огонь!
Hrethgir 13.01.2025
По прошлому проекту в Logisim Evolution https:/ / www. cyberforum. ru/ blogs/ 223907/ blog8781. html прилагаю файл архива проекта в Gowin Eda. Восьмибитный счётчик из сумматора+ генератор сигнала. . .
UserScript для подсветки кнопок языков программировани­­­­я в зависимости от текущего раздела
volvo 13.01.2025
В результате работы этого скрипта подсвечиваются нужные кнопки не только в форме быстрого ответа, но и при редактировании сообщения: / / ==UserScript== / / @name CF_DefaultLangSelect / / . . .
Введение в модели и алгоритмы машинного обучения
InfoMaster 12.01.2025
Машинное обучение представляет собой одну из наиболее динамично развивающихся областей искусственного интеллекта, которая фокусируется на разработке алгоритмов и методов, позволяющих компьютерам. . .
Как на Python создать нейросеть для решения задач
InfoMaster 12.01.2025
В контексте стремительного развития современных технологий особое внимание уделяется таким инструментам, как нейросети. Эти структуры, вдохновленные биологическими нейронными сетями, используются для. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru