Форум программистов, компьютерный форум CyberForum.ru

GCC returning reference to temporary - C++

Восстановить пароль Регистрация
 
gromo
 Аватар для gromo
366 / 265 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
02.11.2013, 23:53     GCC returning reference to temporary #1
Например вот так:
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&& ?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.11.2013, 23:53     GCC returning reference to temporary
Посмотрите здесь:

C++ Странная ошибка: [Linker error] undefined reference to `__dyn_tls_init_callback' [Linker error] undefined reference to ld returned 1 exit status
C++ gcc в c++ VS
g++/gcc не компилирует C++
gcc компиляция C++
C++ Глюк gcc?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
02.11.2013, 23:56     GCC returning reference to temporary #2
gromo, у меня ваш пример вообще не компилируется.

Добавлено через 1 минуту
Bash
ошибка: expected unqualified-id before «&&» token
gromo
 Аватар для gromo
366 / 265 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
02.11.2013, 23:56  [ТС]     GCC returning reference to temporary #3
Цитата Сообщение от programina Посмотреть сообщение
у меня ваш пример вообще не компилируется.
чем компилируете? Здесь С++11
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
02.11.2013, 23:58     GCC returning reference to temporary #4
Bash
ошибка: invalid initialization of non-const reference of type «int&» from an rvalue of type «int»
Добавлено через 1 минуту
Теперь компилируется
gromo
 Аватар для gromo
366 / 265 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
03.11.2013, 00:06  [ТС]     GCC returning reference to temporary #5
Цитата Сообщение от programina Посмотреть сообщение
Теперь компилируется
и что, без варнинга?
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
03.11.2013, 00:10     GCC returning reference to temporary #6
gromo, c варнингом.

Цитата Сообщение от Википедия
По стандарту C++ временный объект, появившийся в результате вычисления выражения, можно передавать в функции, но только по константной ссылке (const &). Функция не в состоянии определить, можно ли рассматривать переданный объект как временный и допускающий модификацию (константный объект, который тоже может быть передан по такой ссылке, нельзя модифицировать (легально)). Это не проблема для простейших структур наподобие complex, но для сложных типов, требующих выделения-освобождения памяти, уничтожение временного объекта и создание постоянного может отнимать много времени, в то время как можно было бы просто перенаправить указатели.
ct0r
C++/Haskell
 Аватар для ct0r
1549 / 568 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
03.11.2013, 00:14     GCC returning reference to temporary #7
Цитата Сообщение от gromo Посмотреть сообщение
Почему вылазиит данный warning? Если обернуть return func2(); функцией std::move(), то все ОК.
Я к тому, что возвращенное func2() значение уже является rvalue, зачем его еще кастовать к T&& ?
Вылазит потому что rvalue reference - эта та же ссылка, но только на rvalue. А возвращать ссылку на локальный объект функции - это создавать баг.
std::move роли не играет, так как тут он ничего не делает. А при нем варнинг исчезает только из-за усложнения кода для анализа (мало ли что может вернуть std::move).
gromo
 Аватар для gromo
366 / 265 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
03.11.2013, 00:34  [ТС]     GCC returning reference to temporary #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/reference/u.../move/?kw=move

Ну и на всякий случай:
ISO/IEC 14882:2011
Draft: n3690
Миниатюры
GCC returning reference to temporary  
ct0r
C++/Haskell
 Аватар для ct0r
1549 / 568 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
03.11.2013, 00:38     GCC returning reference to temporary #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, поскольку не имеет имени. Но это я и так знаю.
gromo
 Аватар для gromo
366 / 265 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
03.11.2013, 00:51  [ТС]     GCC returning reference to temporary #10
Цитата Сообщение от ct0r Посмотреть сообщение
move делает из rvalue rvalue-reference, которая тоже является rvalue, поскольку не имеет имени.
Зачем "делать" из rvalue rvalue-reference? По-моему компилятор не должен выводить предупреждение в 10 строке.
std::move() делает из lvalue rvalue-reference. Поэтому и возник вопрос - почему если обернуть и так временный объект, возвращаемый func2() в move(), то варнинг исчезает.
Может я в чем-то не прав, поправьте, пожалуйста.
ct0r
C++/Haskell
 Аватар для ct0r
1549 / 568 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
03.11.2013, 01:11     GCC returning reference to temporary #11
Ты в move передаешь что? rvalue. Что делает move? Грубо говоря, он делает static_cast<int&&>. У нас получается rvalue reference, у которого нет имени. Значит это rvalue. Ты возвращаешь ссылку на rvalue - на временный объект, который будет уничтожен. Это баг.
gromo
 Аватар для gromo
366 / 265 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
03.11.2013, 01:28  [ТС]     GCC returning reference to temporary #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  
ct0r
C++/Haskell
 Аватар для ct0r
1549 / 568 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
03.11.2013, 12:01     GCC returning reference to temporary #13
Цитата Сообщение от gromo Посмотреть сообщение
Хорошо, а что если так
А ничего не изменилось. Чтобы все работало правильно, надо из func1 возвращать значение. Возврат rvalue reference - это редко когда нужно.

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

Цитата Сообщение от gromo Посмотреть сообщение
Ей даже можно присвоить литерал, и потом получить его адрес (адрес ЛИТЕРАЛА).
Можно, потому что она тут lvalue, а литерал prvalue. И никаких локальных объектов, уничтожающихся при выходе из области, тут нет, - время жизни ссылки здесь ровно такое же, как и объекта.
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
03.11.2013, 12:33     GCC returning reference to temporary #14
Цитата Сообщение от gromo Посмотреть сообщение
Почему вылазиит данный warning?
А где данный warning?
gromo
 Аватар для gromo
366 / 265 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
03.11.2013, 13:11  [ТС]     GCC returning reference to temporary #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();
^


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

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

Не по теме:

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

gromo
 Аватар для gromo
366 / 265 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
03.11.2013, 13:48  [ТС]     GCC returning reference to temporary #17
Цитата Сообщение от OhMyGodSoLong Посмотреть сообщение
Ну или move-конструктор, если строка — это единственное, что надо вернуть.
То есть, получается, для строк и типов, которые внутри хранят указатели на дин.память move-semantics оправдана, а для фундаментальных типов уже не работает, потому что они разрушатся?
ct0r
C++/Haskell
 Аватар для ct0r
1549 / 568 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
03.11.2013, 13:57     GCC returning reference to temporary #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 оправдана, а для фундаментальных типов уже не работает, потому что они разрушатся?
Семантика перемещения оправдана, когда нужно уметь красть ресурсы или когда объект может быть только перемещаемым. Не совсем понял про разрушение фундаментальных типов.
gromo
 Аватар для gromo
366 / 265 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
03.11.2013, 15:08  [ТС]     GCC returning reference to temporary #19
Цитата Сообщение от ct0r Посмотреть сообщение
Не совсем понял про разрушение фундаментальных типов.
А это я заработался немножко бред написал
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.11.2013, 15:23     GCC returning reference to temporary
Еще ссылки по теме:

Компиляция gcc C++
GotoXY в GCC C++

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

Или воспользуйтесь поиском по форуму:
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
03.11.2013, 15:23     GCC returning reference to temporary #20
Цитата Сообщение от gromo Посмотреть сообщение
То есть, получается, для строк и типов, которые внутри хранят указатели на дин.память move-semantics оправдана, а для фундаментальных типов уже не работает, потому что они разрушатся?
Move-семантика не работает для фундаментальных типов, потому что это типы-значения. Не типы-объекты. Вы никак не можете отличить один (int) 42 от другого (int) 42. И даже от (long) 42 не можете. И это никак не исправить. Поэтому переменным фундаментальных типов выдан такой особый статус.
Yandex
Объявления
03.11.2013, 15:23     GCC returning reference to temporary
Ответ Создать тему
Опции темы

Текущее время: 23:48. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru