88 / 88 / 80
Регистрация: 25.08.2013
Сообщений: 337
1

&& ссылки на r-value

01.04.2016, 10:05. Показов 7060. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Плохо понял что из себя представляют ссылки r-value.
C++
1
2
3
4
5
6
7
8
9
10
11
    int z = 0;
    int &&a = 2 + 2;    // выражение 2 + 2 возвращает r-value
    int &&b = z;        // (ошибка) выражение z возвращает l-value                 
    a = 3 + 3;          //  r-value
 
    a = z;              // а так почему можно?
    // a превратилось в обычную переменную? и вот:
    int &&x = 1;
    int &&y = 2;
    x = y;
    int &&k = x;        // ошибка...???
Я понимаю, что они были придуманы для конструктора перемещения, чтобы l значение интерпретировать как r и перемещать без копирования. (так же, чтобы учитывать временные объекты без копирования)
Но чем именно являются отдельно определенные ссылки r-value не понял.
И вообще, они где-нибудь используются именно в таком виде, чтоб определить например string &&z?
Чем она дальше будет отличаться от обычной переменной типа string?
Буду рад любым комментариям.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.04.2016, 10:05
Ответы с готовыми решениями:

Ошибка: multiple definition of `void std::swap<A>(A&amp;, A&amp;)
Хочу специализировать swap для своего класса. Получаю ошибку. Вот код:#ifndef A_H #define A_H ...

Почему friend ostrem& operator <<(ostream& outs, const Rational&); - invalid function declaration?
Пытаюсь скомпилировать программу пишет friend ostrem&amp; operator &lt;&lt;(ostream&amp; outs, const...

В заштрихованную фигуру бросают точки с координатами x и y. Получить координаты первой точки не попавшей в эту область (фигура x*x+y*y<25&&x*x+y*y>=9&
В заштрихованную фигуру бросают точки с координатами x и y. Получить координаты первой точки не...

ostream &operator<< (ostream &output, const Array &obj) - что означает эта строка?
void Array::getArray() // вывод массива { for (int ix = 0; ix &lt; size; ix++) cout &lt;&lt;...

6
Вездепух
Эксперт CЭксперт С++
11691 / 6370 / 1723
Регистрация: 18.10.2014
Сообщений: 16,052
01.04.2016, 12:33 2
Лучший ответ Сообщение было отмечено yrceus как решение

Решение

Цитата Сообщение от yrceus Посмотреть сообщение
Я понимаю, что они были придуманы для конструктора перемещения,
Не только. Во-первых, перемещения бывают не только в конструкторе. Само перемещение вы реализуете своими руками. Где вы реализуете перемещение - там оно и будет.

Во-вторых, perfect forwarding - тоже цель rvalue-ссылок.

В-третьих, может какие еще применения удастся им найти. Вот Мейерс предлагает концепцию universal reference.

Цитата Сообщение от yrceus Посмотреть сообщение
Но чем именно являются отдельно определенные ссылки r-value не понял.
Ссылкой. Именованная rvalue ссылка - это просто lvalue, как и обычная ссылка.

Цитата Сообщение от yrceus Посмотреть сообщение
И вообще, они где-нибудь используются именно в таком виде, чтоб определить например string &&z?
В определении отдельностоящей rvalue-ссылки не больше смысла, чем в определении отдельностоящей обычной (lvalue) ссылки, с той только разницей, что rvalue-ссылка может привязываться к rvalue, не имея при этом квалификатора const. (Обычная ссылка должна быть const, чтобы привязываться к rvalue).

Цитата Сообщение от yrceus Посмотреть сообщение
Чем она дальше будет отличаться от обычной переменной типа string?
На концептуальном уровне - ничем. (На физическом уровне, понятное дело, она может оказаться указателем.) Точно так же обычная const string &r = string("abc"); ссылка внешне не отличается от const string s("abc"); переменной. Только в случае rvalue-ссылки const - не обязателен.
1
88 / 88 / 80
Регистрация: 25.08.2013
Сообщений: 337
02.04.2016, 11:36  [ТС] 3
Фух, статью Мейерса осилил, можно сказать что понял. Понял, что если для && ссылки происходит выведение типа, то это в большинстве случаев универсальная ссылка. Мотаю на ус
C++
1
2
3
int x = 0;
auto &&y = x; // работает
y = 5 + 5; // тоже работает
В большинстве, но не всегда, необходимо смотреть по контексту, существуют случаи где даже при выведении типа, сам тип уже предопределен (в случае с push_back).
Так же существует сжатие ссылок:
C++
1
Widget& && var2 = var1;          // note reference-to-reference
var2 (подразумевается ссылка на ссылку) происходит "reference collapsing", после чего var2 интерпретируется как простая ссылка. Это как ниже:
C++
1
2
3
    int x;
    int &z = x;
    auto &&s = z;// s простая ссылка &
Плюс по поиску perfect forwarding на хабре статью нашел, Идеальная передача и универсальные ссылки тоже Мейерса упоминают, но доходчивее пишут, на русском все-таки. В целом успокоился по поводу r ссылок, в голове уложилось. В который раз огромнейшее спасибо за ответ!

Добавлено через 17 часов 8 минут
TheCalligrapher, буквально на секунду вернуться к теме. Вы написали,
перемещения бывают не только в конструкторе. Само перемещение вы реализуете своими руками. Где вы реализуете перемещение - там оно и будет.
Но как же не в конструкторе? Если объект не имеет конструктора перемещения, то его и переместить нельзя, только копировать, никакие ссылки не помогут) Или нет, я что-то упускаю? Или речь шла о какой-нибудь функции подобной конструктору перемещения? Которая в случае r-value будет освобождать память и менять адрес (как конструктор перемещения).
0
2835 / 1644 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
02.04.2016, 11:59 4
Цитата Сообщение от yrceus Посмотреть сообщение
Но как же не в конструкторе?
Имеется в виду, например, swap:
C++
1
2
3
T t = std::move(a);
a = std::move(b);
b = std::move(t);
1
88 / 88 / 80
Регистрация: 25.08.2013
Сообщений: 337
02.04.2016, 12:20  [ТС] 5
Да, а если объекты типа T не имеют конструктора перемещения и он не синтезирован компилятором? То произойдет обычное копирование?
То есть перемещение все равно в конструкторе перемещения происходит, да? Так или иначе.
И для простых типов функция move() бесполезна, просто приведет их значение к типу &&. (не бесполезна, но в данном случае не отработает как ожидается)
C++
1
2
3
4
double a = 3.14;
double b = std::move(a);
//эквивалентно
double b = a; // правильно?
0
Вездепух
Эксперт CЭксперт С++
11691 / 6370 / 1723
Регистрация: 18.10.2014
Сообщений: 16,052
02.04.2016, 22:17 6
Лучший ответ Сообщение было отмечено yrceus как решение

Решение

Цитата Сообщение от yrceus Посмотреть сообщение
Но как же не в конструкторе? Если объект не имеет конструктора перемещения, то его и переместить нельзя, только копировать, никакие ссылки не помогут) Или нет, я что-то упускаю? Или речь шла о какой-нибудь функции подобной конструктору перемещения? Которая в случае r-value будет освобождать память и менять адрес (как конструктор перемещения).
Не совсем понимаю, что вы хотите здесь сказать. Во-первых, перемещенеим объекта занимается, например, перемещающий оператор присваивания. И никакоих конструкторов в этом процессе не участвует. Это уже сразу говорит о том, что перемещение возможно без конструктора перемещения.

Во-вторых, никто вам не запрещает написать свою функцию

C++
1
2
3
4
void i_wanna_move_it(SomeClass &dst, SomeClass &&src)
{
  ...
}
в которой вы просто явно руками выдерете все потроха из объекта src и переместите их в объект dst. Никаких конструкторов, никаких операторов присваивания.

Более того, еще раз, все это мы уже давно делали и в классическом C++, и в С. Вопрос был только в том, какие выработать соглашения и как описать семантику фукнций, чтобы пользователь был в курсе, что призойдет при вызове функции. Каждый делал это по-своему.

Все, что появилось с появлением официальой концепции move semantics - это набор стандартизованных примитивов, которые своей стандартизованностью должны облегчать написание/понимание кода. Плюс они своей стандартизованностью позволяют и компилятору пользоваться преимуществами move semantics для ваших типов (если вы ее реализовали).

Добавлено через 2 минуты
Цитата Сообщение от yrceus Посмотреть сообщение
И для простых типов функция move() бесполезна, просто приведет их значение к типу &&.
Функция std::move для всех типов делает только то, что приводит значение к типу &&. Что происходит с типом && в правой части присваивания и инициализации зависит от свойств типа. Для скалярных типов происходит просто копирование значения.
1
88 / 88 / 80
Регистрация: 25.08.2013
Сообщений: 337
02.04.2016, 23:39  [ТС] 7
Отлично, спасибо! Объяснили, поправили и подтвердили, остается только запомнить
0
02.04.2016, 23:39
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.04.2016, 23:39
Помогаю со студенческими работами здесь

Порядок вычисления: операторы «|» и «||», «&» и «&&»
В Java булевые операторы «|» и «||», и «&amp;» и «&amp;&amp;» отличаются друг от друга порядком вычеслений, а в...

C2280 "bulb &bulb::operator =(const bulb &)": предпринята попытка ссылки на удаленную функцию
Есть некий класс моей реализации под названием bulb, когда я пытаюсь сделать удаление объектов...

Friend ostream& operator<<(ostream& stream, CArr& obj);
CArr.h #pragma once class CArr{ int* arr = nullptr; int size = 10; void swap(int *a, int...

Создать функцию с параметрами GetFunctionValue(double& a, double& b, double& c, double& x)...
Есть код что считает нужно сделать пару манипуляций что у не могу реализовать 1) создать функцию...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru