Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Ferrari F1
619 / 513 / 101
Регистрация: 27.01.2015
Сообщений: 2,981
Записей в блоге: 1
Завершенные тесты: 1
#1

Ссылки на r-значения - C++

04.08.2016, 09:33. Просмотров 540. Ответов 21
Метки нет (Все метки)

Дарова!
Знакомлюсь с r-value reference и как то трудно получается полностью вникнуть в них.
Так, например, возникает ошибка в main, но ведь ссылка может выступать как l значение
C++
1
2
3
4
5
6
7
8
9
10
int&& func()
{
    int i(1);
    return i + 2;
}
 
int main()
{
    func() = 8;
}
Или даже так, все равно то же самое
C++
1
2
3
4
5
6
7
8
9
10
int&& func()
{
    int i(1);
    return std::move(i + 2);
}
 
int main()
{
    func() = 8;
}
Добавлено через 25 минут
Или вот еще вопрос, верно ли, что в этом коде не происходит лишних копирований, т.е.
1) сперва вызывается func
2) потом в func вычисляется значение выражения i + 2
3) по завершению вычисления создается временная безымянная переменная, которая хранит результат
4) эта безымянная переменная инициализирует параметр функции move
5) move возвращает r-value ссылку
6) func возвращает r value ссылку, полученную как результат move

7) в main результат вызова func в контексте инициализации интерпритируется как r-value типа int
8) x связывается с этим r-value
C++
1
2
3
4
5
6
7
8
9
10
int&& func()
{
    int i(1);
    return std::move(i + 2);
}
 
int main()
{
    auto&& x = func();
}
Добавлено через 3 минуты
еще 1 вопрос, почему компиль выдает варнинг в этом коде
warning C4172: возвращение адреса локальной или временной переменной
C++
1
2
3
4
5
6
7
8
9
10
int&& func()
{
    int i(1);
    return i + 2; // ИЗМЕНЕНИЯ ПРОИЗОШЛИ ЗДЕСЬ
}
 
int main()
{
    auto&& x = func();
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.08.2016, 09:33
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Ссылки на r-значения (C++):

operator= возврат значения и просто ссылки - C++
Здорова господа! Снова пытаюсь чуток в С++ разобраться, с перегрузкой операций, снова ничерта непонятно. от допустим класс class...

Возвращение ссылки на указатель использование её как левостороннего значения - C++
Есть шаблон: //------------------------------------------------------- template<class T> struct ts { private: void* data; ...

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

Возвращение значения в функции, ссылки, вычислить корни квадратного уравнения - C++
Определить функцию вычисления корней квадратного уравнения. Функция должна возвращать значение 1, если корни найдены, значение 0, если...

Главная функция (вводит некоторые значения и передает их и ссылки на некоторые переменные в функцию) - C++
Написать главную функцию, которая вводит некоторые значения и передает их и ссылки на некоторые переменные в функцию. Получив результаты...

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

21
nimazzzy
Заблокирован
04.08.2016, 10:02 #2
Потому что ты возвращаешь ссылку на локальную переменную, которая уже не существует вне функции.
0
notAll
425 / 146 / 36
Регистрация: 27.05.2016
Сообщений: 393
Завершенные тесты: 2
04.08.2016, 10:11 #3
Ferrari F1, возвращать ссылки из функций можно на объекты, которые живут после ее вызова. С ссылками на rvalue можно написать как то так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
std::vector<int>&& func1(std::vector<int>& v)
{
    v.push_back(42);
    return std::move(v); //std::move скастит v с lvalue до rvalue
}
 
std::vector<int> func2()
{
    std::vector<int> v{1,2,3};
    return v; // будет перемещен
}
 
int main()
{
    std::vector<int> v{1,2,3};
    auto v2 = func1(v);
    std::cout << "v.size = " << v.size() << "\n";
    std::cout << "v2.size = " << v2.size() << "\n";
 
    auto v3 = func2();
    std::cout << "v3.size = " << v3.size() << "\n";
}
Добавлено через 3 минуты
А вот так писать не стоит, это UB:
C++
1
2
3
4
5
std::vector<int>&& func3()
{
    std::vector<int> v{1,2,3};
    return std::move(v);
}
0
Ferrari F1
619 / 513 / 101
Регистрация: 27.01.2015
Сообщений: 2,981
Записей в блоге: 1
Завершенные тесты: 1
04.08.2016, 10:34  [ТС] #4
Цитата Сообщение от nimazzzy Посмотреть сообщение
Потому что ты возвращаешь ссылку
ну так возвращается r-value ссылка, а не обычная l-value, следовательно она должна каким магическим образом (фиг знает каким) ссылаться на временное значение - в этом и есть смысл r value ссылки. А то, стирается эта переменная из стека или нет, меня это не волнует, забота об этом ложиться на плечи разработчиков компилятора.

Если переменная из стека трется, то почему в этом коде все ок?
C++
1
2
3
4
5
6
7
8
9
10
int&& func()
{
    int i(1);
    return std::move(i + 2);
}
 
int main()
{
    auto&& x = func();
}
Добавлено через 19 минут
Или вот еще вопрос, почему этот код некорректный?
C++
1
2
3
4
5
6
int main()
{
    int x = 2;
    x = std::move(x) = 3;
    system("pause");
}
0
nimazzzy
Заблокирован
04.08.2016, 10:38 #5
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
ну так возвращается r-value ссылка, а не обычная l-value, следовательно она должна каким магическим образом (фиг знает каким) ссылаться на временное значение - в этом и есть смысл r value ссылки.
Нет, смысл rvalue ссылки совсем не в этом.
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
Если переменная из стека трется, то почему в этом коде все ок?
В этом коде как раз не все ок
0
Ferrari F1
619 / 513 / 101
Регистрация: 27.01.2015
Сообщений: 2,981
Записей в блоге: 1
Завершенные тесты: 1
04.08.2016, 10:41  [ТС] #6
Цитата Сообщение от notAll Посмотреть сообщение
C++
1
auto v2 = func1(v);
тут используется к-тор перемещения?

Добавлено через 1 минуту
Цитата Сообщение от nimazzzy Посмотреть сообщение
В этом коде как раз не все ок
от компилятора (msvs) не поступило ни одного варнинга/ошибки
0
notAll
425 / 146 / 36
Регистрация: 27.05.2016
Сообщений: 393
Завершенные тесты: 2
04.08.2016, 10:44 #7
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
тут используется к-тор перемещения?
Да.
0
Ferrari F1
619 / 513 / 101
Регистрация: 27.01.2015
Сообщений: 2,981
Записей в блоге: 1
Завершенные тесты: 1
04.08.2016, 10:47  [ТС] #8
notAll, а возможно ли, что такое преобразуется из
C++
1
auto v2 = func1(v);
в
C++
1
auto v2(std::vector<int>(func1(v)));
?

А это в свою очередь является к-тором копирования, ведь вами была использована не прямая инициализация объекта.
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
04.08.2016, 10:56 #9
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
от компилятора (msvs) не поступило ни одного варнинга/ошибки
Потому что ты ее замаскировал для компилятора вызовом move. В move делается статик каст, а любой явный каст как бы говорит: "я знаю, что делаю, компилятор - не мешай мне". Вот он и не мешает.

Цитата Сообщение от Ferrari F1 Посмотреть сообщение
почему этот код некорректный?
Потому же, почему этот код некорректный:
C++
1
2
3
4
5
int foo() { return 1; }
int main()
{
    foo() = 1;
}
Стандартом запрещается изменять временные объекты встроенных типов.
Где-то тут была тема с моим участием, где про это рассказывалось.
А вот, нашел: Временные объекты встроенного типа
1
notAll
425 / 146 / 36
Регистрация: 27.05.2016
Сообщений: 393
Завершенные тесты: 2
04.08.2016, 11:18 #10
Что то я засомневался вот в этом коде:
C++
1
2
3
4
5
6
7
8
9
10
11
std::vector<int>&& func() // return xrvalue
{
    std::vector<int> v{1,2,3};
    return std::move(v);
}
 
int main()
{
    auto&& x = func();
    std::vector<int> v(x);
}
Это законно или все же UB?
0
Ferrari F1
619 / 513 / 101
Регистрация: 27.01.2015
Сообщений: 2,981
Записей в блоге: 1
Завершенные тесты: 1
04.08.2016, 11:24  [ТС] #11
notAll,
C++
1
2
3
4
5
std::vector<int> func2()
{
    std::vector<int> v{ 1,2,3 };
    return v; // будет перемещен
}
Можешь объяснить, почему v будет именно перемещен?
0
notAll
425 / 146 / 36
Регистрация: 27.05.2016
Сообщений: 393
Завершенные тесты: 2
04.08.2016, 11:36 #12
Компилятор оптимизирует. Почитай про NRVO.

Добавлено через 46 секунд
Или вот: c++11 Return value optimization or move?

Добавлено через 3 минуты
И еще: Замечание по move semantics при операторе return в C++11
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
04.08.2016, 12:00 #13
Цитата Сообщение от notAll Посмотреть сообщение
Это законно или все же UB?
Это UB.

Цитата Сообщение от notAll Посмотреть сообщение
Почитай про NRVO.
C++
1
2
3
4
5
std::vector<int> func2()
{
    std::vector<int> v{ 1,2,3 };
    return v; // будет перемещен
}
NRVO тут будет, но перемещения (в терминах С++11) не будет. Это же разные механизмы так-то.
1
hoggy
6701 / 2883 / 494
Регистрация: 15.11.2014
Сообщений: 6,480
Завершенные тесты: 1
04.08.2016, 12:06 #14
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
А то, стирается эта переменная из стека или нет, меня это не волнует, забота об этом ложиться на плечи разработчиков компилятора.
разработчиков компиляторов мало волнует ваше некомпетентное мнение.

Цитата Сообщение от Ferrari F1 Посмотреть сообщение
Если переменная из стека трется, то почему в этом коде все ок?
там не все ок.
там все оч и оч плохо.

Цитата Сообщение от notAll Посмотреть сообщение
Это законно или все же UB?
UB

Добавлено через 3 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
NRVO тут будет, но перемещения (в терминах С++11) не будет. Это же разные механизмы так-то.
зависет от использования.

вот так будет NRVO:

C++
1
auto v = func2();
а вот так r-value:

C++
1
2
some obj;
obj = func();
2
DrOffset
04.08.2016, 12:43     Ссылки на r-значения
  #15

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
зависет от использования.
Да, согласен.

notAll, я там фигню написал. Конечно же при наличии move конструктора (а у вектора он есть) и отсутствии других препятствий к этому, он будет делать перемещение. Другое дело, что не всегда эффект будет сопровождаться фактичеким перемещением (сопровождаться работой move конструктора), если возможно сделать (N)RVO оптимизацию.

0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.08.2016, 12:43
Привет! Вот еще темы с ответами:

Вычислить значения функции F на интервале от начального значения до конечного значения - C++
Написать консольное приложение на С++ Перепечатайте пожалуйста текст задания на форум.

Выбор значения из ссылки - Delphi
Доброго времени суток, форумчане! Прошу сильно не ругать, если мой вопрос покажется глупым, - я честно проштудировал много информации,...

Работа с потоками, выполняющими методы принимающими значения ссылки - C#
Ребята, как сделать так, чтобы можно было через делегат ParametrizedThreadStart можно было передавать параметр ссылку. Пример ...

Изменение ссылки(добавление/обновление значения из input), при помощи jquery - jQuery
Нужно при помощи jquery в конец ссылки добавлять значение, введенное в инпуте. Я сделал таким образом: HTML: &lt;input name=&quot;vvod&quot;...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru