Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
3 / 3 / 2
Регистрация: 21.02.2015
Сообщений: 77

Rvalue reference

21.03.2017, 20:29. Показов 1261. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
 
std::string get_string()
{
    return std::string("12345");
}
 
int main()
{
    std::string const& str = get_string();
    std::cout << str << std::endl;
    return 0;
}
Как вообще такой код может работать? Я привык, что нельзя получить ссылку на временный обьект, а тут не только ее получили, а еще и используют дальше...Разве временный обьект не действует в течении выражения, в котором он обьявлен?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.03.2017, 20:29
Ответы с готовыми решениями:

C++ expressions - rvalue, glvalue, prvalue, xvalue, lvalue, а также rvalue reference: что есть что?
Доброго времени суток, не понимаю до конца деление С++ - выражений (приложение 1). Lvalue вроде просто - всё, от чего можно брать адрес. А...

RVALUE Ссылка, error: cannot bind non-const lvalue reference of type 'String&' to an rvalue of type 'String'|
Код не компилируется ниже 17 стандарта с++ с ошибкой error: cannot bind non-const lvalue reference of type 'String&amp;' to an rvalue of...

Rvalue reference
Добрый вечер! Помогите пожалуйста разобраться с rvalue reference: template &lt;class T&gt; void fun(T&amp;&amp; x){ } ...

14
4949 / 2289 / 287
Регистрация: 01.03.2013
Сообщений: 5,991
Записей в блоге: 32
21.03.2017, 20:41
Оооо, узнаю брата Колю! (С) Буквально на днях мне любезно рассказывали про это, хотя я мало что понял Но рискну предположить, что в строке 10 у вас правое пр-валью (как результат возврата объекта из функции) присваивается левому л-валью (при связи с именем как константной ссылке), и это "продлевает жизнь объекта" (С).

ЗЫ Nosey, это Вы? Так проверяете усвоение материала?
0
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
21.03.2017, 20:44
Временный объект живет пока на него есть ссылка.
1
3 / 3 / 2
Регистрация: 21.02.2015
Сообщений: 77
21.03.2017, 20:44  [ТС]
_Ivana, нет, я, к сожалению(или к счастью?), не Nosey.
Но рискну предположить, что в строке 10 у вас правое пр-валью присваивается левому л-валью (при связи с именем как константной ссылке)
не совсем понял, если честно
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
21.03.2017, 20:48
Цитата Сообщение от ACTIONFENIX Посмотреть сообщение
Разве временный обьект не действует в течении выражения, в котором он обьявлен?
константная ссылка продлевает жизнь временного объекта.

http://alenacpp.blogspot.ru/2008/01/const.html?m=1

Добавлено через 1 минуту
Цитата Сообщение от notAll Посмотреть сообщение
Временный объект живет пока на него есть ссылка.
только если она c квалификатором const
1
4949 / 2289 / 287
Регистрация: 01.03.2013
Сообщений: 5,991
Записей в блоге: 32
21.03.2017, 20:49
Да я сам не совсем понял Но помню, что при присваивании правый пр-валью объект каким-то волшебным образом становится л-валью, когда мы связываем его значение с именем при присваивании по константной ссылке. Так что str - это уже л-валью объект, если не ошибаюсь.

ЗЫ и вроде при присваивании по str&& мы получаем слева р-валью (каламбур), который можем перекастить САМИ РУКАМИ (и только) к х-валью (стд::мувом или каким-то еще мутабором), и это тоже продлит жизнь объекта и позволит его переиспользование. Но тут я тоже не уверен, потому как слышал один раз и без практики такого колдунства
0
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
21.03.2017, 20:50
Цитата Сообщение от hoggy Посмотреть сообщение
только если она c квалификатором const
Да да:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct Test
{
    ~Test() {puts("~Test()");}
};
 
Test foo() { return Test();}
 
int main()
{
    {
        const Test &ref = foo();
        std::cout << "End of Life 1\n";
    }
    {
        foo();
        std::cout << "End of Life 2\n";
    }
}
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
21.03.2017, 21:45
Цитата Сообщение от hoggy Посмотреть сообщение
только если она c квалификатором const
Это относится к "примитивным" типам и не всегда относится к классовым типам:
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
#include <iostream>
 
class Foo {};
 
Foo foo() { return Foo(); }
int bar() { return 42; }
 
class Baz
{
public:
    operator Foo() {
        return Foo();
    }
};
 
int main()
{
    const Foo& a = foo(); // OK
    Foo& b = foo(); // OK Foo - классовый тип
 
    const int& c = bar(); // OK
    // int& d = bar(); // Error int - не класс
    int&& d = bar(); // OK
 
    Baz baz;
 
    const Foo &e = baz; // OK
    Foo&& foo = baz; // OK 
    // Foo &f = baz; // Error - при конверсии либо конст, либо &&
 
}
Причем, напомню: в своей области видимости rvalue-ссылка - lvalue.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,221
21.03.2017, 22:05
Цитата Сообщение от avgoor Посмотреть сообщение
Это относится к "примитивным" типам и не всегда относится к классовым типам:
Это всегда относится ко всем типам.

Цитата Сообщение от avgoor Посмотреть сообщение
C++
1
Foo& b = foo(); // OK Foo - классовый тип
Нет, ни в коем случае. Это - ошибка.

Code
1
2
main.cpp:19:17: error: invalid initialization of non-const reference of type 'Foo&' from an rvalue of type 'Foo'
     Foo& b = foo(); // OK Foo - классовый тип
(А дальше пошли rvalue references, которые к теме не относятся.)
1
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
21.03.2017, 22:11
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Нет, ни в коем случае. Это - ошибка.
Из 14-го стандарта:
— If the initializer expression
— is an xvalue (but not a bit-field), class prvalue, array prvalue or function lvalue and “cv1 T1”
is reference-compatible with “cv2 T2”, or
— has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be
converted to an xvalue, class prvalue, or function lvalue of type “cv3 T3”, where “cv1 T1” is
reference-compatible with “cv3 T3” (see 13.3.1.6),
then the reference is bound to the value of the initializer expression in the first case and to
the result of the conversion in the second case (or, in either case, to an appropriate base class
107) This requires a conversion function (12.3.2) returning a reference type.
In the second case, if the reference is an rvalue reference and the second standard conversion
sequence of the user-defined conversion sequence includes an lvalue-to-rvalue conversion,
the program is ill-formed.
0
284 / 232 / 114
Регистрация: 07.09.2016
Сообщений: 584
21.03.2017, 22:22
Временный объект живет пока на него есть ссылка.
Будьте бдительны. Из этой фразы можно подумать, что будут работать корректно все тесты. Однако работает только первый. В остальных случаях деструкторы отрабатывают внутри функций, хотя вроде как ссылки существуют
или их копии или хз что:
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <string>
#include <iostream>
 
struct Trace
{
  Trace()
  {
    std::cout << "Trace::Trace: " << this << std::endl;
  }
 
  Trace(const Trace& other)
  {
    std::cout << "Trace::Trace(" << &other << "): " << this << std::endl;
  }
 
  ~Trace()
  {
    std::cout << "Trace::~Trace: " << this << std::endl;
  }
 
};
 
 
Trace foo1()
{
  return Trace();
}
 
const Trace& foo2()
{
  Trace trace;
  const Trace& traceRef = trace;
  return traceRef;
}
 
const Trace& foo3()
{
  Trace trace;
  Trace&& traceRefRef = std::move(trace);
  const Trace& traceRef = traceRefRef;
  return traceRef;
}
 
const Trace& foo4()
{
  const Trace& traceRef = foo1();
  return traceRef;
}
 
const Trace& foo5()
{
  return foo1();
}
 
 
template <typename F>
void runTest(const std::string& name, F func)
{
    std::cout << std::endl << std::endl << "----------------------" << std::endl;
 
    const Trace& trace = func();
    trace;
    std::cout << "after " << name << std::endl;
}
 
int main()
{
  runTest("foo1", &foo1);
  runTest("foo2", &foo2);
  runTest("foo3", &foo3);
  runTest("foo4", &foo4);
  runTest("foo5", &foo5);
}
Добавлено через 5 минут
output:
----------------------
Trace::Trace: 0052FA23
after foo1
Trace::~Trace: 0052FA23


----------------------
Trace::Trace: 0052F95B
Trace::~Trace: 0052F95B
after foo2


----------------------
Trace::Trace: 0052F95B
Trace::~Trace: 0052F95B
after foo3


----------------------
Trace::Trace: 0052F94F
Trace::~Trace: 0052F94F
after foo4


----------------------
Trace::Trace: 0052F89B
Trace::~Trace: 0052F89B
after foo5
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
21.03.2017, 22:27
Цитата Сообщение от avgoor Посмотреть сообщение
Foo& b = foo(); // OK Foo - классовый тип
это не по стандарту
error: invalid initialization of non-const reference of type ‘Foo&’ from an rvalue of type ‘Foo’
Пусть вас не удивляет прекрасно работающий в Visual Studio пример:

std::vector<int> &v = std::vector<int>({ 1, 2, 3 });
v.push_back(4);

Ответ появится только на 4 уровне предупреждений:

warning C4239: nonstandard extension used
note: A non-const reference may only be bound to an lvalue

Это нестандартное для C++ расширение отключается ключом /Za (Disable Language Extensions), но некоторые хедеры, типа Windows.h, не будут компилироваться, так как в расширение входят и другие фичи.
(ц)

https://habrahabr.ru/post/322132/
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
21.03.2017, 22:33
Цитата Сообщение от hoggy Посмотреть сообщение
это не по стандарту
Я ткнул ссылку в стандарт в 10 посте. Может быть, я там что-то не так понял. Тогда что там написано?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12937 / 6804 / 1821
Регистрация: 18.10.2014
Сообщений: 17,221
21.03.2017, 22:34
Цитата Сообщение от avgoor Посмотреть сообщение
Из 14-го стандарта:
Ваша цитата "из 14-го стандарта" выхвачена из пункта 8.5.3/5 (5.2), который начинается словами

"-- Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference."

Т.е. если рассматривать lvalue ссылки, то все, что вы процитировали, относится только к константным ссылкам. Ваш пример не удовлетворяет этому требованию.
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
21.03.2017, 22:38
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Ваш пример не удовлетворяет этому требованию.
Да, признаю, не туда посмотрел. Сбила с толку именно студия.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.03.2017, 22:38
Помогаю со студенческими работами здесь

Rvalue reference and lambda
void foo(A&amp;&amp; a) { auto l = () {}; //a? } Как передать в лямбду rvalue ref как просто ссылку? Чтобы потом использовать...

std::move, rvalue reference
Здравствуйте! Недавно начал разбираться с новыми способами передачи аргументов. Прочитал около 10 статей, некоторые на русском, некоторые...

Rvalue reference. Что происходит в коде?
В консоли пусто. Но &quot;worked&quot; выводит. Почему? #include &lt;iostream&gt; using std::cout; class Example { public: Example(){ ...

Возвращаемый тип как rvalue reference
Нашел интересный пример в книге Мейерса Эффективный и современный С++. class Widget { public: using DataType =...

Ссылка на rvalue, является ли она сама rvalue?
А верно ли, что ссылка на rvalue сама не является rvalue? Вот такой код является валидным: #include &lt;iostream&gt; int main() { ...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru