383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
1

GCC returning reference to temporary

02.11.2013, 23:53. Показов 4904. Ответов 19
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Например вот так:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int func2()
{
    int input;
    cin >> input;
    return input;
}
 
int&& func1()
{
    return func2();
}
 
int main()
{
    cout <<func1() << endl;
    return 0;
}
Почему вылазиит данный warning? Если обернуть return func2(); функцией std::move(), то все ОК.
Я к тому, что возвращенное func2() значение уже является rvalue, зачем его еще кастовать к T&& ?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.11.2013, 23:53
Ответы с готовыми решениями:

Предупреждение: returning address of local variable or temporary
Есть код программы для кодирования в base64 и обратно, не самый лучший код, но все же. И вот...

Binding reference to a temporary
Есть код #include &lt;iostream&gt; struct S { S() { std::cout &lt;&lt; __PRETTY_FUNCTION__...

Ошибка undefined reference в Eclipse (Winodows,C++,MinGW,GCC)
При попытке скомпилировать проект с подключенной библиотекой liblm.a(сторонняя библиотека)...

Undefined reference to pow() почему в университете gcc такое выдает, а дома нет?
В университете стоит линукс и при обращении к библиотекам из math.h линковщик выводит такую ошибку....

19
2062 / 618 / 41
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
02.11.2013, 23:56 2
gromo, у меня ваш пример вообще не компилируется.

Добавлено через 1 минуту
Bash
ошибка: expected unqualified-id before «&&» token
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
02.11.2013, 23:56  [ТС] 3
Цитата Сообщение от programina Посмотреть сообщение
у меня ваш пример вообще не компилируется.
чем компилируете? Здесь С++11
0
2062 / 618 / 41
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
02.11.2013, 23:58 4
Bash
ошибка: invalid initialization of non-const reference of type «int&» from an rvalue of type «int»
Добавлено через 1 минуту
Теперь компилируется
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
03.11.2013, 00:06  [ТС] 5
Цитата Сообщение от programina Посмотреть сообщение
Теперь компилируется
и что, без варнинга?
0
2062 / 618 / 41
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
03.11.2013, 00:10 6
gromo, c варнингом.

Цитата Сообщение от Википедия
По стандарту C++ временный объект, появившийся в результате вычисления выражения, можно передавать в функции, но только по константной ссылке (const &). Функция не в состоянии определить, можно ли рассматривать переданный объект как временный и допускающий модификацию (константный объект, который тоже может быть передан по такой ссылке, нельзя модифицировать (легально)). Это не проблема для простейших структур наподобие complex, но для сложных типов, требующих выделения-освобождения памяти, уничтожение временного объекта и создание постоянного может отнимать много времени, в то время как можно было бы просто перенаправить указатели.
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
03.11.2013, 00:14 7
Цитата Сообщение от gromo Посмотреть сообщение
Почему вылазиит данный warning? Если обернуть return func2(); функцией std::move(), то все ОК.
Я к тому, что возвращенное func2() значение уже является rvalue, зачем его еще кастовать к T&& ?
Вылазит потому что rvalue reference - эта та же ссылка, но только на rvalue. А возвращать ссылку на локальный объект функции - это создавать баг.
std::move роли не играет, так как тут он ничего не делает. А при нем варнинг исчезает только из-за усложнения кода для анализа (мало ли что может вернуть std::move).
1
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
03.11.2013, 00:34  [ТС] 8
Цитата Сообщение от programina Посмотреть сообщение
gromo, c варнингом.
Originally Posted by Википедия
По стандарту C++ временный объект, появившийся в результате вычисления выражения, можно передавать в функции, но только по константной ссылке (const &). Функция не в состоянии определить, можно ли рассматривать переданный объект как временный и допускающий модификацию (константный объект, который тоже может быть передан по такой ссылке, нельзя модифицировать (легально)). Это не проблема для простейших структур наподобие complex, но для сложных типов, требующих выделения-освобождения памяти, уничтожение временного объекта и создание постоянного может отнимать много времени, в то время как можно было бы просто перенаправить указатели.
RValue-reference, слышали такое?

Добавлено через 12 минут
Цитата Сообщение от ct0r Посмотреть сообщение
Вылазит потому что rvalue reference - эта та же ссылка, но только на rvalue. А возвращать ссылку на локальный объект функции - это создавать баг.
std::move роли не играет, так как тут он ничего не делает. А при нем варнинг исчезает только из-за усложнения кода для анализа (мало ли что может вернуть std::move).
From cplusplus.com:
Generally, rvalues are values whose address cannot be obtained by dereferencing them, either because they are literals or because they are temporary in nature (such as values returned by functions or explicit constructor calls). By passing an object to this function, an rvalue that refers to it is obtained.
Source: http://www.cplusplus.com/refer... e/?kw=move

Ну и на всякий случай:
ISO/IEC 14882:2011
Draft: n3690
Миниатюры
GCC returning reference to temporary  
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
03.11.2013, 00:38 9
Цитата Сообщение от gromo Посмотреть сообщение
Generally, rvalues are values whose address cannot be obtained by dereferencing them, either because they are literals or because they are temporary in nature (such as values returned by functions or explicit constructor calls). By passing an object to this function, an rvalue that refers to it is obtained.
Можешь объяснить, к чему ты это привел? Тут написано, что такое rvalues и что move делает из rvalue rvalue-reference, которая тоже является rvalue, поскольку не имеет имени. Но это я и так знаю.
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
03.11.2013, 00:51  [ТС] 10
Цитата Сообщение от ct0r Посмотреть сообщение
move делает из rvalue rvalue-reference, которая тоже является rvalue, поскольку не имеет имени.
Зачем "делать" из rvalue rvalue-reference? По-моему компилятор не должен выводить предупреждение в 10 строке.
std::move() делает из lvalue rvalue-reference. Поэтому и возник вопрос - почему если обернуть и так временный объект, возвращаемый func2() в move(), то варнинг исчезает.
Может я в чем-то не прав, поправьте, пожалуйста.
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
03.11.2013, 01:11 11
Ты в move передаешь что? rvalue. Что делает move? Грубо говоря, он делает static_cast<int&&>. У нас получается rvalue reference, у которого нет имени. Значит это rvalue. Ты возвращаешь ссылку на rvalue - на временный объект, который будет уничтожен. Это баг.
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
03.11.2013, 01:28  [ТС] 12
Цитата Сообщение от ct0r Посмотреть сообщение
Ты возвращаешь ссылку на rvalue - на временный объект, который будет уничтожен. Это баг.
Хорошо, а что если так:
C++ (Qt)
1
2
3
4
5
6
7
// func1() func2() как и раньше
int main()
{
    int && sss = func1();
    cout << sss << endl;
    return 0;
}
здесь мы быстренько "подхватили" этот временный, впоследствии разрушаемый временный объект, возвращаемый func1().
Я вижу, что вы выше писали, что rvalue-reference это та же ссылка, только на rvalue. Но она же предназначена как раз таки "давать имя" временным объектам. Ей даже можно присвоить литерал, и потом получить его адрес (адрес ЛИТЕРАЛА).
C++ (Qt)
1
2
3
4
5
6
int main()
{
    int && literal = 25;
    cout << &literal <<endl;
    return 0;
}
Все сказанное в этом посте не касается функции std::move
Миниатюры
GCC returning reference to temporary  
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
03.11.2013, 12:01 13
Цитата Сообщение от gromo Посмотреть сообщение
Хорошо, а что если так
А ничего не изменилось. Чтобы все работало правильно, надо из func1 возвращать значение. Возврат rvalue reference - это редко когда нужно.

Цитата Сообщение от gromo Посмотреть сообщение
здесь мы быстренько "подхватили" этот временный, впоследствии разрушаемый временный объект, возвращаемый func1()
По сути мы подхватили ссылку в никуда. rvalue reference - это не магия, она не может спасти локальный объект от уничтожения.

Цитата Сообщение от gromo Посмотреть сообщение
Ей даже можно присвоить литерал, и потом получить его адрес (адрес ЛИТЕРАЛА).
Можно, потому что она тут lvalue, а литерал prvalue. И никаких локальных объектов, уничтожающихся при выходе из области, тут нет, - время жизни ссылки здесь ровно такое же, как и объекта.
1
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
03.11.2013, 12:33 14
Цитата Сообщение от gromo Посмотреть сообщение
Почему вылазиит данный warning?
А где данный warning?
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
03.11.2013, 13:11  [ТС] 15
Цитата Сообщение от ct0r Посмотреть сообщение
Возврат rvalue reference - это редко когда нужно.
С большим трудом, до меня дошло, спасибо Но что значит вот это (со стандарта):
An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that its
resources may be moved, for example
). An xvalue is the result of certain kinds of expressions involving
rvalue references (8.3.2). [ Example: The result of calling a function whose return type is an rvalue
reference is an xvalue.
— end example ]
Цитата Сообщение от ct0r Посмотреть сообщение
std::move роли не играет, так как тут он ничего не делает. А при нем варнинг исчезает только из-за усложнения кода для анализа (мало ли что может вернуть std::move).
а если вместо move поставить, например, std::abs(), то варнинг не исчезает.

И что в случае возврата больших значений из функции? Мне, например, нужно часто возвращать из функции объекты типа string размером в несколько сотен мебибайт. Не лучше ли их переместить как XValue вместо возврата по значению? Иногда такую оптимизацию делает сам компилятор, когда может.

Добавлено через 1 минуту
Цитата Сообщение от castaway Посмотреть сообщение
А где данный warning?
В 10 строке: returning reference to temporary [-Wreturn-local-addr]
return func2();
^


он еще в названии темы написан
0
~ Эврика! ~
1257 / 1006 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
03.11.2013, 13:35 16
Цитата Сообщение от gromo Посмотреть сообщение
И что в случае возврата больших значений из функции? Мне, например, нужно часто возвращать из функции объекты типа string размером в несколько сотен мебибайт.
И они, конечно же, создаются на стеке. Для этого уже давно есть out-параметры и смарт-поинтеры, куда можно засунуть указатель на эту строку. Ну или move-конструктор, если строка — это единственное, что надо вернуть.

Rvalue reference как и временные объекты живут до окончания ближайшего вычисляемого выражения. Их нельзя сохранить куда-то самих по себе, чтобы они выжили до следующего выражения.

Не по теме:

Цитата Сообщение от gromo Посмотреть сообщение
мебибайт
Мибиби.

2
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
03.11.2013, 13:48  [ТС] 17
Цитата Сообщение от OhMyGodSoLong Посмотреть сообщение
Ну или move-конструктор, если строка — это единственное, что надо вернуть.
То есть, получается, для строк и типов, которые внутри хранят указатели на дин.память move-semantics оправдана, а для фундаментальных типов уже не работает, потому что они разрушатся?
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
03.11.2013, 13:57 18
Цитата Сообщение от gromo Посмотреть сообщение
С большим трудом, до меня дошло, спасибо
Если хочешь до конца разобраться с rvalue reference, посмотри еще universal reference и perfect forwarding.

Цитата Сообщение от gromo Посмотреть сообщение
Но что значит вот это (со стандарта)
Это значит, что безымянная rvalue reference - это xvalue. И что может быть перемещение ресурсов, если возвращать, например, std::move(член класса);

Цитата Сообщение от gromo Посмотреть сообщение
а если вместо move поставить, например, std::abs(), то варнинг не исчезает.
Ну тут компилятору очевидно, что это локальный объект, потому что это abs возвращает просто значение.

Цитата Сообщение от gromo Посмотреть сообщение
И что в случае возврата больших значений из функции? Мне, например, нужно часто возвращать из функции объекты типа string размером в несколько сотен мебибайт. Не лучше ли их переместить как XValue вместо возврата по значению? Иногда такую оптимизацию делает сам компилятор, когда может.
Если не пользоваться динамической памятью, то как вариант стоит посмотреть на RVO и copy elision.

Цитата Сообщение от gromo Посмотреть сообщение
То есть, получается, для строк и типов, которые внутри хранят указатели на дин.память move-semantics оправдана, а для фундаментальных типов уже не работает, потому что они разрушатся?
Семантика перемещения оправдана, когда нужно уметь красть ресурсы или когда объект может быть только перемещаемым. Не совсем понял про разрушение фундаментальных типов.
1
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
03.11.2013, 15:08  [ТС] 19
Цитата Сообщение от ct0r Посмотреть сообщение
Не совсем понял про разрушение фундаментальных типов.
А это я заработался немножко бред написал
0
~ Эврика! ~
1257 / 1006 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
03.11.2013, 15:23 20
Цитата Сообщение от gromo Посмотреть сообщение
То есть, получается, для строк и типов, которые внутри хранят указатели на дин.память move-semantics оправдана, а для фундаментальных типов уже не работает, потому что они разрушатся?
Move-семантика не работает для фундаментальных типов, потому что это типы-значения. Не типы-объекты. Вы никак не можете отличить один (int) 42 от другого (int) 42. И даже от (long) 42 не можете. И это никак не исправить. Поэтому переменным фундаментальных типов выдан такой особый статус.
1
03.11.2013, 15:23
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.11.2013, 15:23
Помогаю со студенческими работами здесь

GCC Сборка 32 разрядной версии GCC 64 разрядным GCC
Доброго времени суток. Возникла необходимость под 32х разрядный Linux, собрать 32 разрядный GCC. Но...

Ошибки underfined reference to parentClass::method и unerfined reference to vtable при линковке
При сборке компилятор выдает ошибки underfined reference to и unerfined reference to vtable. Есть...

Insert into . returning
Хочу получить в коллекцию id записей которые я только что заинсертил, но почему-то не получается...

Предложение Returning
База Oracle. Возник такой вопрос. Я в TUpdateSql вешаю запрос: insert into NPATS_GTP (NAME,...


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

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

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