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

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

Войти
Регистрация
Восстановить пароль
 
 
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
#1

GCC returning reference to temporary - C++

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

Например вот так:
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++):

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

Ошибки underfined reference to parentClass::method и unerfined reference to vtable при линковке - C++
При сборке компилятор выдает ошибки underfined reference to и unerfined reference to vtable. Есть базовый класс, два наследуемых от него и...

Исправить ошибку "C2562: 'main': 'void' function returning a value" - C++
Привет программистам. Не могу разобраться с ошибкой &quot;C2562: 'main': 'void' function returning a value&quot;. Помогите чем можете. #include...

Странная ошибка: [Linker error] undefined reference to `__dyn_tls_init_callback' [Linker error] undefined reference to ld returned 1 exit status - C++
Здравствуйте. Вот недавно начал изучать книгу &quot;С++ для чайников&quot; Стефан Р. Девис 4-е издание. И напоролся на кучу ошибок) Но смог все...

Почему возникает ошибка "function returning function is not allowed" - C++
Подключаю заголовочный файл .dll библиотеки, возникают ошибки #pragma once #include &lt;vector&gt; struct RSA_Interface { ...

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

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
02.11.2013, 23:56 #2
gromo, у меня ваш пример вообще не компилируется.

Добавлено через 1 минуту
Bash
ошибка: expected unqualified-id before «&&» token
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
02.11.2013, 23:56  [ТС] #3
Цитата Сообщение от programina Посмотреть сообщение
у меня ваш пример вообще не компилируется.
чем компилируете? Здесь С++11
programina
1914 / 599 / 37
Регистрация: 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 минуту
Теперь компилируется
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
03.11.2013, 00:06  [ТС] #5
Цитата Сообщение от programina Посмотреть сообщение
Теперь компилируется
и что, без варнинга?
programina
1914 / 599 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
03.11.2013, 00:10 #6
gromo, c варнингом.

Цитата Сообщение от Википедия
По стандарту C++ временный объект, появившийся в результате вычисления выражения, можно передавать в функции, но только по константной ссылке (const &). Функция не в состоянии определить, можно ли рассматривать переданный объект как временный и допускающий модификацию (константный объект, который тоже может быть передан по такой ссылке, нельзя модифицировать (легально)). Это не проблема для простейших структур наподобие complex, но для сложных типов, требующих выделения-освобождения памяти, уничтожение временного объекта и создание постоянного может отнимать много времени, в то время как можно было бы просто перенаправить указатели.
ct0r
Игогошка!
1769 / 671 / 42
Регистрация: 19.08.2012
Сообщений: 1,284
Завершенные тесты: 1
03.11.2013, 00:14 #7
Цитата Сообщение от gromo Посмотреть сообщение
Почему вылазиит данный warning? Если обернуть return func2(); функцией std::move(), то все ОК.
Я к тому, что возвращенное func2() значение уже является rvalue, зачем его еще кастовать к T&& ?
Вылазит потому что rvalue reference - эта та же ссылка, но только на rvalue. А возвращать ссылку на локальный объект функции - это создавать баг.
std::move роли не играет, так как тут он ничего не делает. А при нем варнинг исчезает только из-за усложнения кода для анализа (мало ли что может вернуть std::move).
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
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/reference/u.../move/?kw=move

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

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

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


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

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

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

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

Read returning value of main() from terminal - C Linux
How i can read main() returning value from terminal(tty) ? int main(){ return 0; } int main(){ return 1; } How...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
03.11.2013, 13:11
Ответ Создать тему
Опции темы

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