Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Toshkarik
1148 / 865 / 90
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
#1

Ссылка на временный объект - C++

11.08.2014, 03:24. Просмотров 1329. Ответов 24
Метки нет (Все метки)

Наткнулся тут в гугле на одну интересную тему.
Как известно, данный код не соответствует стандарту, и не будет скомпилирован многими современными компиляторами:

C++
1
2
3
4
5
6
7
8
9
10
11
class A {
 
};
 
void f( A & ) {
   
}
 
int main() {
   f( A());
}
Но данный код компилируется, и вполне валиден:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A {
public:
   A &getThis() {
      return *this;
   }
};
 
void f( A & ) {
   
}
 
int main() {
   f( A().getThis());
}
Собственно, вопрос: почему он валиден?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.08.2014, 03:24
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Ссылка на временный объект (C++):

Временный объект
Требуется создать при помощи конструктора временный объект. Затем присвоить...

Временный объект и конструктор копирования
Добрый день! Столкнулся c задачкой в тесте: class A{ public: A(){ ...

Возвращение const ссылки на временный объект
Добрый вечер, #include <iostream> using namespace std; struct Point {...

интерфейс, в методе которого создается объект типа IDictionary и возвращается ссылка на этот объект
Привет всем. Необходимо реализовать интерфейс, в методе которого создается...

Ссылка на объект класса
class Aclass{ public: int i=0; void j(){i=2;} }; Aclass f(){ ...

Ссылка на объект, возвращаемый функцией
Безопасно ли подобное? typedef std::vector< string > vec; vec someFoo();...

24
CyberSolver
101 / 74 / 17
Регистрация: 23.07.2014
Сообщений: 852
Записей в блоге: 1
11.08.2014, 07:27 #2
Toshkarik, в первом случае ссылка на временный объект, вы сами себе и ответили. Во-втором — функция возвращает ссылку на A, у функции такие же параметры. Почему это не должно скомпилироваться?
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
11.08.2014, 08:56 #3
Цитата Сообщение от Toshkarik Посмотреть сообщение
Собственно, вопрос: почему он валиден?
Выражение A(); является rvalue. Причем неконстантным rvalue.
Метод getThis() возвращает lvalue.
Потому и валиден.
0
Toshkarik
1148 / 865 / 90
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
11.08.2014, 12:51  [ТС] #4
Почему компилируется понянто. Вопрос в другом, почему в этом случая временный объект живет до выхода из функции. Интересует не техническая часть, а почему это допустили. По сути мы схитрили и все же использовали временный объект для передали по ссылке в качестве параметра.
0
0x10
2554 / 1734 / 285
Регистрация: 24.11.2012
Сообщений: 4,361
11.08.2014, 12:58 #5
Toshkarik, временные объекты пока выполняется выражение.
Мб кто-нибудь приведет прямо ссылку на стандарт.
0
soon
2545 / 1310 / 177
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
11.08.2014, 13:04 #6
N3337 12.2/3

When an implementation introduces a temporary object of a class that has a non-trivial constructor (12.1, 12.8), it shall ensure that a constructor is called for the temporary object. Similarly, the destructor shall be called for a temporary with a non-trivial destructor (12.4). Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception. The value computations and side effects of destroying a temporary object are associated only with the full-expression, not with any specific subexpression.
1
Toshkarik
1148 / 865 / 90
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
11.08.2014, 13:07  [ТС] #7
И про это в курсе, имеется в виду full-expression, ссылку на стандарт сейчас не дам, так как не помню. Может опять неправильно выразился. Попробуем наоборот: если возможен второй вариант, то почему запретили первый? Это же выглядит немного как "хак". Может быть, это одна из причин появления rvalue-reference в C++11...

Не по теме:

upd: А вот и стандарт :)

0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
11.08.2014, 13:19 #8
Toshkarik, Как-то спрашивал про то, почему разрешена конверсия от rvalue к lvalue на SO, впринципе там ответили довольно полно: http://stackoverflow.com/questions/1...-visual-studio
2
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
11.08.2014, 13:39 #9
Цитата Сообщение от Toshkarik Посмотреть сообщение
почему запретили первый?
Это попытка запретить опасное использование. Если я не ошибаюсь, то предложение запрета первого варианта исходил от самого Страуструпа. А второй вариант запретить нельзя. Потому что, например, его не отличить вот от такого (пример утрирован):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A {
public:
   A(A * ref) : ref_(ref) {}
   A() : ref_(this) {}
   A &getThis() {
      return *ref_;
   }
   A * ref_;
};
 
void f( A & ) {
   
}
 
int main() {
   A a;
   f( A(&a).getThis());
}
1
Tulosba
:)
Эксперт С++
4746 / 3240 / 496
Регистрация: 19.02.2013
Сообщений: 9,046
11.08.2014, 14:02 #10
Цитата Сообщение от Toshkarik Посмотреть сообщение
По сути мы схитрили
Именно в этом всё дело. Стандарт дает (старается дать) защиту от явных ошибок. Но когда программист хочет обойти защиту, он ее обойдет.
1
Toshkarik
1148 / 865 / 90
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
11.08.2014, 14:23  [ТС] #11
Так ведь непонятно в данном случае - от чего защищают?
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
11.08.2014, 14:27 #12
Toshkarik, Не знаю насколько я буду прав, но первый вариант не должен работать для POD типов, для них ведь никак не сэмулировать второй вариант. В то время как для классов вцелом может.

C++
1
2
3
4
5
6
7
8
void function(int& v)
{
}
 
int main()
{
   function(1);
}
Мы пытаемся привязать константу к lvalue-reference, что абсолютно неверно.
0
Tulosba
:)
Эксперт С++
4746 / 3240 / 496
Регистрация: 19.02.2013
Сообщений: 9,046
11.08.2014, 14:29 #13
Цитата Сообщение от Toshkarik Посмотреть сообщение
Так ведь непонятно в данном случае - от чего защищают?
От бесполезной модификации временного объекта.
0
Toshkarik
1148 / 865 / 90
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
11.08.2014, 14:46  [ТС] #14
ForEveR, сейчас вопрос уже не в эмуляции, а в самом запрете. Ведь вполне можно было создать временный объект, даже POD, и передать его в функцию по ссылке, если гарантируется его время жизни ( временного объекта ).

Цитата Сообщение от Tulosba Посмотреть сообщение
От бесполезной модификации временного объекта.
Ну почему сразу бесполезной, вполне можно найти полезное применение. Ведь это одна из целей, как я понимаю, rvalue reference. Возможно, ошибаюсь.
0
Tulosba
:)
Эксперт С++
4746 / 3240 / 496
Регистрация: 19.02.2013
Сообщений: 9,046
11.08.2014, 14:48 #15
Цитата Сообщение от Toshkarik Посмотреть сообщение
Ну почему сразу бесполезной, вполне можно найти полезное применение.
Как оно может быть полезным, если объект будет уничтожен после всех манипуляций?
0
Toshkarik
1148 / 865 / 90
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
11.08.2014, 15:02  [ТС] #16
Я уже не найду, наверно, статью, в которой показывались новшества C++11 и способы достижения некоторых из них в C++03( 98 ). Я ведь не настаиваю ни на чем. Просто хотелось бы понять "создателей" языка/стандартов. Если бы небыло хоть в чем то полезным, то я не нашел бы этого способа в интернете. Конечно, я понимаю, что экспериментаторов тоже хватает.
0
0x10
2554 / 1734 / 285
Регистрация: 24.11.2012
Сообщений: 4,361
11.08.2014, 15:38 #17
Цитата Сообщение от Toshkarik Посмотреть сообщение
Просто хотелось бы понять "создателей" языка/стандартов.
Они не боги, а такие же люди. Не каждая возможность языка имеет глубокий смысл и кейс к применению, где иначе было бы нельзя.
"If you think C++ is not overly complicated, just what is a “protected abstract virtual base pure virtual private destructor,” and when was the last time you needed one?", - Tom Cargill (1990).
Цитата взята с седьмого слайда доклада: https://tech.yandex.ru/events/cpp-party/june-msk/talks/1954/
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
11.08.2014, 18:11 #18
Цитата Сообщение от Toshkarik Посмотреть сообщение
Просто хотелось бы понять "создателей" языка/стандартов.
Защита в том числе от висячих ссылок. Уж больно просто их создать становится.
C++
1
2
С & c = C();
c.foo(); // fail
А так конечно любую защиту можно сломать, и если ты сейчас приведешь пяток способов создать висячую ссылку, то это не будет значить, что я не прав. А будет значить только лишь то, что нет в мире совершенных инструментов (наш мозг в том числе).
0
Croessmah
++Ͻ
14161 / 8086 / 1513
Регистрация: 27.09.2012
Сообщений: 19,929
Записей в блоге: 3
Завершенные тесты: 1
11.08.2014, 21:08 #19
C++
1
2
С & c = C();
c.foo(); // fail
DrOffset, а как же:
There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression. The first context is when a default constructor is called to initialize an element of an array. If the constructor has one or more default arguments, the destruction of every temporary created in a default argument is sequenced before the construction of the next array element, if any.


The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:
— A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.
— A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call.
— The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.
— A temporary bound to a reference in a new-initializer (5.3.4) persists until the completion of the full-expression containing the new-initializer.

The destruction of a temporary whose lifetime is not extended by being bound to a reference is sequenced before the destruction of every temporary which is constructed earlier in the same full-expression. If the lifetime of two or more temporaries to which references are bound ends at the same point, these temporaries are destroyed at that point in the reverse order of the completion of their construction. In addition, the destruction of temporaries bound to references shall take into account the ordering of destruction of objects with static, thread, or automatic storage duration
1
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
11.08.2014, 21:41 #20
Цитата Сообщение от Croessmah Посмотреть сообщение
а как же:
Все это хорошо, только не понятно к чему ты это написал. Никаких откровений я тут не увидел.
Я честно пытался угадать что ты имел в виду, но что-то не выходит. Поясни.

Добавлено через 8 минут
Хотя я кажется догадался. Если каким-либо образом нарушить вышеописанные правила, то получим висячие ссылки. Ну так на это у меня как раз была заготовлена фраза:
Цитата Сообщение от DrOffset Посмотреть сообщение
если ты сейчас приведешь пяток способов создать висячую ссылку, то это не будет значить, что я не прав. А будет значить только лишь то, что нет в мире совершенных инструментов (наш мозг в том числе).
С++ не из тех языков, которые будут поддерживать штаны разработчика. Следовательно ожидать от него чрезмерной заботы не стоит. Достаточно уже того, что все эти моменты описаны в стандарте. Если подумать, то легко можно объяснить, почему такие вещи не запрещены синтаксисом. Я думаю, ты и сам это знаешь.
0
11.08.2014, 21:41
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.08.2014, 21:41
Привет! Вот еще темы с решениями:

Ссылка на объект класса в массиве
Вообщем есть класс THypergraph в котором находятся два массива объектов класса...

Что лучше: ссылка или объект?
привет, задался таким вопросом: как лучше поступать в следующей ситуации? ...

Ссылка на объект не указывает на экземпляр объекта
Подскажите, в чем ошибка и как исправить. struct Node{ Node *prev;...

Ссылка на объект как свойство класса
Добрый вечер. Есть 2 класса: сотрудники и компании. Если использовать БД то...


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

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

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