Re[7]: Правомерно ли такое
От: T4r4sB Россия  
Дата: 18.08.20 16:33
Оценка:
Здравствуйте, rg45, Вы писали:

R>Так это и есть битая ссылка, раз объект мертвый.


Скажем так, ссылка ведёт на объект, находящийся на стеке в вызывающей функции. То есть формально она не битая. И если бы у объекта не было деструктора, то ссылка бы вообще делала вид, что всё ништяк.

R>Попробуй использовать, например, std::string вместо int — спецэффекты будут поинтереснее.


Да то же самое примерно
; Function Attrs: noinline nounwind optnone uwtable
define linkonce_odr dso_local dereferenceable(32) %struct.IntWrapper* @"??$test@UIntWrapper@@@@YAAEAUIntWrapper@@$$QEAU0@@Z"(%struct.IntWrapper* dereferenceable(32) %0) #1 comdat {
  %2 = alloca %struct.IntWrapper*, align 8
  store %struct.IntWrapper* %0, %struct.IntWrapper** %2, align 8
  %3 = load %struct.IntWrapper*, %struct.IntWrapper** %2, align 8
  ret %struct.IntWrapper* %3
}

То есть ссылка возвращается нормальная. Дальше по коду строка разрушается сразу после вызова этой функции, если вывести что-то на экран, то выводится пустая строка.
Re[8]: Правомерно ли такое
От: rg45 СССР  
Дата: 18.08.20 17:39
Оценка: +2 -1
Здравствуйте, T4r4sB, Вы писали:

TB>Скажем так, ссылка ведёт на объект, находящийся на стеке в вызывающей функции. То есть формально она не битая. И если бы у объекта не было деструктора, то ссылка бы вообще делала вид, что всё ништяк.


Давай по порядочку.

Во-первых, деструктор формально есть у любого типа данных, даже у int. И его даже можно явно позвать: http://coliru.stacked-crooked.com/a/8360b8eef0155e2c. Просто деструктор такая хитрая штука, что он может быть определен пользователем, а может быть сгенерирован компилятором. Деструктор может быть тривиальным и нетривиальным. Но он есть всегда. И время жизни объекта, согласно стандарту, закачивается, ПРИ ВХОДЕ, в деструктор (даже если он формальный — в этом случае просто где вход, там и выход).

Во-вторых, сразу же после инициализации auto&& i = test(IntWrapper(0)); время жизни объекта IntWrapper сразу же заканчивается. От него остается только область памяти, которой компилятор может распоряжаться по своему усмотрению. Например, он может разместить в ней объект(ы) какого-нибудь типа, массивы, вообще все, что угодно. Если ты начнешь постепенно усложнять свой пример, ты в этом убедишься рано или поздно. Поэтому любое использование объекта после окончания его времени жизни ведет к UB — согласно стандарту, ессно. Несмотря на то, что ссылка указывает на валидную область памяти, ее объекта в этой области уже нет и пользоваться такой ссылкой нельзя. Вот такие ссылки, которые пережили свои объекты и которыми нельзя пользоваться, я и называю "битыми".
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 18.08.2020 17:45 rg45 . Предыдущая версия . Еще …
Отредактировано 18.08.2020 17:43 rg45 . Предыдущая версия .
Отредактировано 18.08.2020 17:42 rg45 . Предыдущая версия .
Отредактировано 18.08.2020 17:40 rg45 . Предыдущая версия .
Re[9]: Правомерно ли такое
От: T4r4sB Россия  
Дата: 18.08.20 17:44
Оценка:
Здравствуйте, rg45, Вы писали:

R>Давай по порядочку.


Да, согласен, пользоваться такой ссылкой нельзя.
Другой вопрос: а чего добились кресты, уничтожая временные объекты в конце текущего выражения, а не в конце операторного блока? По расходу памяти — копейки. Зато геморроя лишнего много.
Re[10]: Правомерно ли такое
От: rg45 СССР  
Дата: 18.08.20 17:57
Оценка:
Здравствуйте, T4r4sB, Вы писали:


TB>Другой вопрос: а чего добились кресты, уничтожая временные объекты в конце текущего выражения, а не в конце операторного блока? По расходу памяти — копейки. Зато геморроя лишнего много.


Ну, я могу только порассуждать на эту тему. По расходу памяти — это ведь смотря как писать код. Размеры блоков не лимитированы и число временных объектов, создаваемых в подвыражениях, могло бы зашкаливать за разумные рамки. А с другой стороны, наверное, не смогли придумать сценариев, когда бы это создавало какие-то непреодолимые трудности.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 18.08.2020 17:58 rg45 . Предыдущая версия .
Re[11]: Правомерно ли такое
От: T4r4sB Россия  
Дата: 18.08.20 18:39
Оценка:
Здравствуйте, rg45, Вы писали:

R>Ну, я могу только порассуждать на эту тему. По расходу памяти — это ведь смотря как писать код. Размеры блоков не лимитированы и число временных объектов, создаваемых в подвыражениях, могло бы зашкаливать за разумные рамки.


На практике я на некотором другом языке (тоже с RAII) писал, там по сути любое выражение вида
f(g())

означало что-то типа
tmp=g();
f(tmp);

И этот tmp жил до конца текущего блока, и что-то стек с кучей от этого не переполнялись.

R>А с другой стороны, наверное, не смогли придумать сценариев, когда бы это создавало какие-то непреодолимые трудности.


Даже на чистом асме нет непреодолимых трудностей.
В данном примере трудность была создана — удалось получить ссылку на объект, у которого уже вызвался деструктор.
Да, она преодолима. Но это трудность, на решение которой будут тратиться лишние человекочасы.
Re[9]: Правомерно ли такое
От: σ  
Дата: 18.08.20 22:30
Оценка:
R>Во-первых, деструктор формально есть у любого типа данных, даже у int. И его даже можно явно позвать: http://coliru.stacked-crooked.com/a/8360b8eef0155e2c. Просто деструктор такая хитрая штука, что он может быть определен пользователем, а может быть сгенерирован компилятором. Деструктор может быть тривиальным и нетривиальным. Но он есть всегда. И время жизни объекта, согласно стандарту, закачивается, ПРИ ВХОДЕ, в деструктор (даже если он формальный — в этом случае просто где вход, там и выход).

Итак, смотрим в C++17 [expr.pseudo]/1:
> The use of a pseudo-destructor-name after a dot . or arrow -> operator represents the destructor for the non-class type denoted by type-name or decltype-specifier. The result shall only be used as the operand for the function call operator (), and the result of such a call has type void. The only effect is the evaluation of the postfix-expression before the dot or arrow.

Никаких вызовов деструкторов (для int) и окончания его жизни...

Да, в C++20 закрыли одно CWG issue и ЕМНИП применили его решение ретроактивно, но никаких вызовов деструкторов для `int` не появилось.
[expr.call]/5:
> If the postfix-expression names a pseudo-destructor (in which case the postfix-expression is a possibly-parenthesized class member access), the function call destroys the object of scalar type denoted by the object expression of the class member access ([expr.ref], [basic.life]).
[basic.life]/1:
> The lifetime of an object o of type T ends when:
> — if T is a non-class type, the object is destroyed, or
> — if T is a class type, the destructor call starts, or
> — the storage which the object occupies is released, or is reused by an object that is not nested within o ([intro.object]).
Отредактировано 18.08.2020 23:02 σ . Предыдущая версия .
Re[10]: Правомерно ли такое
От: rg45 СССР  
Дата: 18.08.20 23:08
Оценка:
Здравствуйте, σ, Вы писали:

σ>Итак, смотрим в C++17 [expr.pseudo]/1:

>> The use of a pseudo-destructor-name after a dot . or arrow -> operator represents the destructor for the non-class type denoted by type-name or decltype-specifier. The result shall only be used as the operand for the function call operator (), and the result of such a call has type void. The only effect is the evaluation of the postfix-expression before the dot or arrow.

σ>Никаких вызовов деструкторов (для int) и окончания его жизни...

σ>Да, в C++20 закрыли одно CWG issue и ЕМНИП применили его решение ретроактивно, но никаких вызовов деструкторов для `int` не появилось.

Я фигею, тетя Клава, с вашей телепередачи.

Во-первых, в данном случае рассматривается время жизни и вызов деструктора объекта типа IntWrapper, а не int.

А во-вторых, говорится же о допустимости выражений с использованием деструкторов в т.ч. для типа int. Ты же зацепился за некорректное использование слова "вызов", которое не делает погоды в данном случае от слова "совсем". Тем более, что сами же они называют это не иначе как "such a call". Да, этот самый CALL имеет ограниченный эффект, но я ничего такого и не утверждал, что этому бы противоречило.

Нельзя же так циклиться на мелочах. Ты за деревьями леса не видишь. И не в первый раз.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 18.08.2020 23:29 rg45 . Предыдущая версия . Еще …
Отредактировано 18.08.2020 23:25 rg45 . Предыдущая версия .
Отредактировано 18.08.2020 23:23 rg45 . Предыдущая версия .
Отредактировано 18.08.2020 23:16 rg45 . Предыдущая версия .
Отредактировано 18.08.2020 23:15 rg45 . Предыдущая версия .
Отредактировано 18.08.2020 23:10 rg45 . Предыдущая версия .
Re[11]: Правомерно ли такое
От: σ  
Дата: 18.08.20 23:28
Оценка:
R>о времени жизни типа int в приведенном примере даже речи не шло, поскольку рассматривалось время жизни объекта типа IntWrapper

R> Во-первых, деструктор формально есть у любого типа данных, даже у int. И его даже можно явно позвать: http://coliru.stacked-crooked.com/a/8360b8eef0155e2c. Просто деструктор такая хитрая штука, что он может быть определен пользователем, а может быть сгенерирован компилятором. Деструктор может быть тривиальным и нетривиальным. Но он есть всегда. И время жизни объекта, согласно стандарту, закачивается, ПРИ ВХОДЕ, в деструктор (даже если он формальный — в этом случае просто где вход, там и выход).


Открываем http://coliru.stacked-crooked.com/a/8360b8eef0155e2c, а там
using Int = int;
Int i = 42;
...
i.~Int();
Хочешь сказать, что это:
R> деструктор формально есть у любого типа данных, даже у int. ... И время жизни объекта, согласно стандарту, закачивается, ПРИ ВХОДЕ, в деструктор (даже если он формальный — в этом случае просто где вход, там и выход).
не про то, что у int формально существует тривиальный сгенерированный компилятором деструктор при вызове которого заканчивается время жизни объекта типа int?
Re[12]: Правомерно ли такое
От: rg45 СССР  
Дата: 18.08.20 23:46
Оценка:
Здравствуйте, σ, Вы писали:

σ>[/ccode]Хочешь сказать, что это:


R> Во-первых, деструктор формально есть у любого типа данных, даже у int. И его даже можно явно позвать: http://coliru.stacked-crooked.com/a/8360b8eef0155e2c. Просто деструктор такая хитрая штука, что он может быть определен пользователем, а может быть сгенерирован компилятором. Деструктор может быть тривиальным и нетривиальным. Но он есть всегда. И время жизни объекта, согласно стандарту, закачивается, ПРИ ВХОДЕ, в деструктор (даже если он формальный — в этом случае просто где вход, там и выход).


σ>не про то, что у int формально существует тривиальный сгенерированный компилятором деструктор при вызове которого заканчивается время жизни объекта типа int?


Хочу сказать, что "формально есть" следует понимать, как "можно написать выражение". Или тебя удивляет, что я не цитирую стандарт по памяти слово в слово?

Ну а то, что после выполнения выражения i.~Int() время жизни i продолжается, для меня новость, признаюсь честно. Спасибо, конечно, но в данном случае это никак не влияет на выводы, поскольку рассматривается время жизни объекта типа IntWrapper, для которого все сказанное мной остается в силе.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 18.08.2020 23:57 rg45 . Предыдущая версия .
Re[9]: Правомерно ли такое
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 19.08.20 09:11
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, ollv, Вы писали:

Так погоди. Давай я сначала попробую сказать точнее, почему я связываю кейсы
  type& v = getrvalue();
  call(getrvalue(), ...);

в обоих случаях происходит инициализация простой ссылки от рвелью. В первом случае это совсем критично, потому как в gcc (я тут даже версию не вспомню версию) есть кейсы, где это компиябильно, но продления жизни для темпорари object не происходит (и еще вопрос, происходит ли тут вообще материализация temporary object), во втором спасает только то, что оно не компилируется. т/к тоже вопрос, если вдруг произойдет кейс, где оно скомпилируется, произойдет ли там материализация temporary obj. И совершенно все равно каким рулом будет продлена жизнь темп объекта.
Видишь ли практик, я считаю, мыслит прецедентарно. Если прецедент был (а он был в практике) эта практика метится как ущербная. В этом случае совсем не тяжело просто перенести создание объекта выше.

O>> Не знаю о чем ты )) к rvalue вполне применим термин lifetime.

BFE>Что обозначает lifetime для rvalue?
Да сплошь и рядом говорят lifetime of rvalue. lifetime of expression
Тут получается небольшой конфликт понятий если rvalue это выражение — то выражение суть понятия из синтаксического анализа. И мы тут перемешиваем понятия из синтаксиса и физики языка. А по сути rvalue — рантайм физика языка, а потому звать его выражением, как его понимать ? это не синтаксическое выражение ? ))
А так понятно, что касательно этого примера исключительно в С++ говорим о object lifetime.

O>>Что касается выражения, синтаксически все, что попадает в конечном счете в АСТ — expression. такова селяви синтаксического анализа.

BFE>И какое отношение это имеет ко времени жизни?
а это и не о времени жизни. это о том, что "rvalue — это выражение". Хоть стандарт и показывает нам именно так, это имхо немного неровно.

O>>Объект — это уже физика языка, так вот живет объект как rvalue, выражением в данном случае будет именно std::vector<int>() -> arg, вот здесь оно и умрет, после инициализации параметра.

BFE>Выражение умрёт? Или умрёт объект?
Давай так ) если считать, что мы принимаем связывание rvalue с простой ссылкой, то работает это правило
 (6.9) — A temporary object bound to a reference parameter in a function call (7.6.1.2) persists until the
completion of the full-expression containing the call.


BFE>>>А вот временные объекты обязаны дожить (по стандарту) до конца выполнения выражения,

O>> Только вот конец выражения будет ровно после запятой (или скобки), std::vector<int>() -> arg.
BFE>Конец full-expression'а?


O>> И если арг не проинициализируется от рвелью и не продлит жизнь объекту, он умрет.

BFE>Если арг не проинициализируется, то и функция вызвана не будет. Причём тут продление жизни для ссылок?

так именно. "если проинициализируется и продлит жизнь". А то может ведь и не продлить (получим битую ссылку в теле)
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Отредактировано 19.08.2020 12:46 Маркуша Шулин . Предыдущая версия .
Re[10]: Правомерно ли такое
От: B0FEE664  
Дата: 19.08.20 16:51
Оценка:
Здравствуйте, ollv, Вы писали:

O> Так погоди. Давай я сначала попробую сказать точнее, почему я связываю кейсы

O>
O>  type& v = getrvalue();
O>  call(getrvalue(), ...);
O>

O> в обоих случаях происходит инициализация простой ссылки от рвелью. В первом случае это совсем критично, потому как в gcc (я тут даже версию не вспомню версию) есть кейсы, где это компиябильно, но продления жизни для темпорари object не происходит (и еще вопрос, происходит ли тут вообще материализация temporary object), во втором спасает только то, что оно не компилируется. т/к тоже вопрос, если вдруг произойдет кейс, где оно скомпилируется, произойдет ли там материализация temporary obj. И совершенно все равно каким рулом будет продлена жизнь темп объекта.

По моим представлением эти два выражения ничем не отличаются с точки зрения жизни временных объектов. Оба временных объекта должны дожить, условно говоря, "до точки с запятой". Я не совсем понимаю зачем нужно расписывать в стандарте "продление жизни" если прямо сказано, что:

Temporary objects are destroyed as the last step in evaluating the full-expression

Можно же написать: getrvalue().print();. Тут тоже есть "продление жизни"?

O>>> Не знаю о чем ты )) к rvalue вполне применим термин lifetime.

BFE>>Что обозначает lifetime для rvalue?
O> Да сплошь и рядом говорят lifetime of rvalue. lifetime of expression
O>Тут получается небольшой конфликт понятий если rvalue это выражение — то выражение суть понятия из синтаксического анализа. И мы тут перемешиваем понятия из синтаксиса и физики языка. А по сути rvalue — рантайм физика языка, а потому звать его выражением, как его понимать ? это не синтаксическое выражение ? ))
O> А так понятно, что касательно этого примера исключительно в С++ говорим о object lifetime.

Видимо из-за этой путаницы терминологии я ничего не понимаю. Есть выражения разных категорий. Они (выражения) могут либо порождать временные объекты, либо нет. Если временные объекты были материализованы, то можно говорить о времени их жизни. Зачем при этом привязывать время жизни временного объекта к категории выражения мне совершенно не понятно. Это же независимые понятия.

O>>>Объект — это уже физика языка, так вот живет объект как rvalue, выражением в данном случае будет именно std::vector<int>() -> arg, вот здесь оно и умрет, после инициализации параметра.

BFE>>Выражение умрёт? Или умрёт объект?
O> Давай так ) если считать, что мы принимаем связывание rvalue с простой ссылкой, то работает это правило
O>
 (6.9) — A temporary object bound to a reference parameter in a function call (7.6.1.2) persists until the
O>completion of the full-expression containing the call.

Зачем нужна эта сентенция, если утверждение процитированное выше —

O>>> И если арг не проинициализируется от рвелью и не продлит жизнь объекту, он умрет.

BFE>>Если арг не проинициализируется, то и функция вызвана не будет. Причём тут продление жизни для ссылок?
O> так именно. "если проинициализируется и продлит жизнь". А то может ведь и не продлить (получим битую ссылку в теле)
Я не могу придумать конструкцию вызова функции без инициализации аргумента.
И каждый день — без права на ошибку...
Re[9]: Правомерно ли такое
От: rg45 СССР  
Дата: 19.08.20 17:13
Оценка: +1 :)
Здравствуйте, B0FEE664, Вы писали:

O>> Не знаю о чем ты )) к rvalue вполне применим термин lifetime.

BFE>Что обозначает lifetime для rvalue?

Ох, пацаны, с огнем играете. Сигма как придет, да как всыплет вам ремня обоим
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[11]: Правомерно ли такое
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 25.08.20 11:04
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, ollv, Вы писали:


O>> Так погоди. Давай я сначала попробую сказать точнее, почему я связываю кейсы

O>>
O>>  type& v = getrvalue();
O>>  call(getrvalue(), ...);
O>>


BFE>По моим представлением эти два выражения ничем не отличаются с точки зрения жизни временных объектов. Оба временных объекта должны дожить, условно говоря, "до точки с запятой".


Вот этимологически как оно было.
https://stackoverrun.com/ru/q/6489490

Таким образом простая ссылка в майкрософт, вела (сейчас они уже по умолчанию отключают такую возможность) себя как константная в стандарте.
Причем замечу

The word const was never present in this section. The rule has always been (from as long as I can remember) that a temporary used to initialize a reference has its lifetime extended to match that of the reference, regardless of the type of the reference.

И, кстати, говорят о продлении lifetime


BFE>Я не совсем понимаю зачем нужно расписывать в стандарте "продление жизни" если прямо сказано, что:

BFE>

BFE>Temporary objects are destroyed as the last step in evaluating the full-expression

Меня вот это и смущает ) то, что мы то ссылаемся на стандарт, то "это проблемы стандарта" ))

BFE>Можно же написать: getrvalue().print();. Тут тоже есть "продление жизни"?

материализация временного объекта, и продление жизни до full-expression. без точки темпорари не создастся. только вот тут момент, опять таки из области синт анализа. Подозреваю, что само понятие full-expression идет именно из грамматики что-то типа
full-expression-body : expression | expression end-of-block full-expression-body
full-expression : full-expression-body end-of-scope

BFE>Видимо из-за этой путаницы терминологии я ничего не понимаю. Есть выражения разных категорий. Они (выражения) могут либо порождать временные объекты, либо нет. Если временные объекты были материализованы, то можно говорить о времени их жизни. Зачем при этом привязывать время жизни временного объекта к категории выражения мне совершенно не понятно. Это же независимые понятия.

Глядя на стандарт и диаграммку

expression
| \
glvalue rvalue
| | \
lvalue xvalue prvalue

Возникают смутные сомнения, что скопипащено оно было с некоей грамматики. Отсюда и это странное смешение — rvalue и выражения. Хотя вот эти ветвления скорее обоснованы структурами синтаксического разбора,

O>>>>Объект — это уже физика языка, так вот живет объект как rvalue, выражением в данном случае будет именно std::vector<int>() -> arg, вот здесь оно и умрет, после инициализации параметра.

BFE>>>Выражение умрёт? Или умрёт объект?
O>> Давай так ) если считать, что мы принимаем связывание rvalue с простой ссылкой, то работает это правило
O>>
 (6.9) — A temporary object bound to a reference parameter in a function call (7.6.1.2) persists until the
O>>completion of the full-expression containing the call.

BFE>Зачем нужна эта сентенция, если утверждение процитированное выше —
Так она с дополнением )) "если считать, что мы принимаем связывание rvalue с простой ссылкой, то работает это правило ...". И именно так оно и должно звучать (имхо) в практических руководствах.
на этом компиляторе видно как работает в данном случае студийный компилятор. тут простой референс ведет себя как константный.
https://rextester.com/l/cpp_online_compiler_visual

#include <iostream>

static int count__ = 0;

struct class_type {
    class_type() {
       ++count__;
    }
    
    class_type(class_type const& ) { ++count__; }
    ~class_type() { --count__; }
    
    void foo(class_type const&, class_type, class_type&) {
         std::cout << "objects: " << count__ << std::endl;
    }
};

int main()
{
    {
        class_type& c0 = class_type();
        c0.foo(class_type(), class_type(), class_type());
        {
            class_type& c1=class_type();
            c1.foo(class_type(), class_type(), class_type());
        }
        c0.foo(class_type(), class_type(), class_type());
    }
    std::cout << "objects: " << count__ << std::endl;
}



O>>>> И если арг не проинициализируется от рвелью и не продлит жизнь объекту, он умрет.

BFE>>>Если арг не проинициализируется, то и функция вызвана не будет. Причём тут продление жизни для ссылок?
O>> так именно. "если проинициализируется и продлит жизнь". А то может ведь и не продлить (получим битую ссылку в теле)
BFE>Я не могу придумать конструкцию вызова функции без инициализации аргумента.

Но я не про инициализацию говорил, я говорил про потенциальную вероятность того, что ссылка окажется битая, т/к каким-то образом не произойдет материализация временного объекта (т/к там просто референс)
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Отредактировано 25.08.2020 11:05 Маркуша Шулин . Предыдущая версия .
Re[12]: Правомерно ли такое
От: B0FEE664  
Дата: 25.08.20 11:59
Оценка:
Здравствуйте, ollv, Вы писали:

O>>> Так погоди. Давай я сначала попробую сказать точнее, почему я связываю кейсы

O>>>
O>>>  type& v = getrvalue();
O>>>  call(getrvalue(), ...);
O>>>


BFE>>По моим представлением эти два выражения ничем не отличаются с точки зрения жизни временных объектов. Оба временных объекта должны дожить, условно говоря, "до точки с запятой".


O>Вот этимологически как оно было.

O>https://stackoverrun.com/ru/q/6489490

O> Таким образом простая ссылка в майкрософт, вела (сейчас они уже по умолчанию отключают такую возможность) себя как константная в стандарте.

O>Причем замечу
O>

The word const was never present in this section. The rule has always been (from as long as I can remember) that a temporary used to initialize a reference has its lifetime extended to match that of the reference, regardless of the type of the reference.

O> И, кстати, говорят о продлении lifetime
Говорят о продлении жизни объекта для ссылки v после выполнения: type& v = getrvalue();.
Это несколько отличается от времени жизни объекта созданного в call(getrvalue(), ...);. После выполнения этого выражения объект созданный в getrvalue() умирает в отличии от объекта на который ссылается v.

  type& v = getrvalue();   // (1)
  call(getrvalue(), ...);  // (2)
  // вот тут у MS обект созданный в (1) продолжает жить, а объект созданный в (2) уже разрушен.

Поэтому, на мой взгляд, говорить о продлении жизни для объекта созданного в call(getrvalue(), ...); смысла нет.

O> Глядя на стандарт и диаграммку

O>expression
O> | \
O>glvalue rvalue
O> | | \
O>lvalue xvalue prvalue
O> Возникают смутные сомнения, что скопипащено оно было с некоей грамматики. Отсюда и это странное смешение — rvalue и выражения. Хотя вот эти ветвления скорее обоснованы структурами синтаксического разбора,

Вот тут я согласен. У меня тоже сложилось впечатление, что вместо описания языка мы имеет описание работы парсера.

O>>>>> И если арг не проинициализируется от рвелью и не продлит жизнь объекту, он умрет.

BFE>>>>Если арг не проинициализируется, то и функция вызвана не будет. Причём тут продление жизни для ссылок?
O>>> так именно. "если проинициализируется и продлит жизнь". А то может ведь и не продлить (получим битую ссылку в теле)
BFE>>Я не могу придумать конструкцию вызова функции без инициализации аргумента.
O>Но я не про инициализацию говорил, я говорил про потенциальную вероятность того, что ссылка окажется битая, т/к каким-то образом не произойдет материализация временного объекта (т/к там просто референс)
Существование ссылки без инициализации запрещено, так что такой ситуации быть не может.
И каждый день — без права на ошибку...
Re[13]: Правомерно ли такое
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 25.08.20 20:56
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, ollv, Вы писали:



BFE>
BFE>  type& v = getrvalue();   // (1)
BFE>  call(getrvalue(), ...);  // (2)
BFE>  // вот тут у MS обект созданный в (1) продолжает жить, а объект созданный в (2) уже разрушен.
BFE>


Я именно и пытался сказать, что ссылка обычная ссылка в МС ведет себя не по стандарту, и позволяет себя инициализировать от rvalue, что по сути и приводит к неоднозначности при переходе от одного компилятора к другому. Именно инициализация простой ссылки от rvalue и есть кривизна / опасность в данном подходе. Что собственно я и пытаюсь утверждать вот уже несколько постов. Разве что мне этимологически стало понятно откуда растут грабли. А именно потому, что майкрософт решила взять поведение ссылки, которое было еще до появления стандарта.

BFE>Поэтому, на мой взгляд, говорить о продлении жизни для объекта созданного в call(getrvalue(), ...); смысла нет.


Я думаю, что вопрос тут скорее о тех кейсах, в которых gcc таки соберет код, в котором идет инициализация ссылки от rvalue, но вот extend lifetime не произойдет (или материализации темп объекта). Имхо такие вещи лучше снабжать комментариями, и пытаться избегать инициализации простой ссылки rvalue. Т/е падение точно было type& r = getrvalue(); т/к здесь шло получение битой ссфлки.

O>> Глядя на стандарт и диаграммку

O>>expression
O>> | \
O>>glvalue rvalue
O>> | | \
O>>lvalue xvalue prvalue
O>> Возникают смутные сомнения, что скопипащено оно было с некоей грамматики. Отсюда и это странное смешение — rvalue и выражения. Хотя вот эти ветвления скорее обоснованы структурами синтаксического разбора,

BFE>Вот тут я согласен. У меня тоже сложилось впечатление, что вместо описания языка мы имеет описание работы парсера.


O>>>>>> И если арг не проинициализируется от рвелью и не продлит жизнь объекту, он умрет.

BFE>>>>>Если арг не проинициализируется, то и функция вызвана не будет. Причём тут продление жизни для ссылок?
O>>>> так именно. "если проинициализируется и продлит жизнь". А то может ведь и не продлить (получим битую ссылку в теле)
BFE>>>Я не могу придумать конструкцию вызова функции без инициализации аргумента.
O>>Но я не про инициализацию говорил, я говорил про потенциальную вероятность того, что ссылка окажется битая, т/к каким-то образом не произойдет материализация временного объекта (т/к там просто референс)
BFE>Существование ссылки без инициализации запрещено, так что такой ситуации быть не может.
Вопрос чем? Речь идет о не безопасности такого подхода вообще.
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[12]: Правомерно ли такое
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 27.08.20 17:54
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, rg45, Вы писали:


R>>Ну, я могу только порассуждать на эту тему. По расходу памяти — это ведь смотря как писать код. Размеры блоков не лимитированы и число временных объектов, создаваемых в подвыражениях, могло бы зашкаливать за разумные рамки.


TB>На практике я на некотором другом языке (тоже с RAII) писал, там по сути любое выражение вида

TB>
TB>f(g())
TB>

TB>означало что-то типа
TB>
TB>tmp=g();
TB>f(tmp);
TB>

TB>И этот tmp жил до конца текущего блока, и что-то стек с кучей от этого не переполнялись.
Ну о куче тут вообще нет разговора, а вот стек ) это до поры до времени. Вот внедрится эта хрень куда-то в рекурсивный разбор,

foo(v = g())
{
foo(g());
// и тут вычисления, что исключит оптимизацию в хвостовую рекурсию и вуаля, стек будет выеден мгновенно
}

R>>А с другой стороны, наверное, не смогли придумать сценариев, когда бы это создавало какие-то непреодолимые трудности.


TB>Даже на чистом асме нет непреодолимых трудностей.

есть, в реальных проектах вполне.

TB>В данном примере трудность была создана — удалось получить ссылку на объект, у которого уже вызвался деструктор.

TB>Да, она преодолима. Но это трудность, на решение которой будут тратиться лишние человекочасы.
Лишние человекочасы это не снос проекта, когда логика изменений для простой задачи размазывается по всему 10*n-летнему коду. или при появлении новых технологий проект безнадежно устаревает, и сделать с ним ничего нельзя.
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[13]: Правомерно ли такое
От: T4r4sB Россия  
Дата: 27.08.20 18:30
Оценка:
Здравствуйте, ollv, Вы писали:

O>foo(v = g())

O>{
O> foo(g());
O> // и тут вычисления, что исключит оптимизацию в хвостовую рекурсию и вуаля, стек будет выеден мгновенно
O>}

Такой случай элементарно обходится, и то мне такое не попадалось. А вот смерть объекта раньше ожидаемого — попадалась.
Re[14]: Правомерно ли такое
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 27.08.20 22:04
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, ollv, Вы писали:


O>>foo(v = g())

O>>{
O>> foo(g());
O>> // и тут вычисления, что исключит оптимизацию в хвостовую рекурсию и вуаля, стек будет выеден мгновенно
O>>}

TB>Такой случай элементарно обходится, и то мне такое не попадалось.

А вот я не сказал бы. Особенно, если на рекурсивном движке построены нетривиальные вычисления, это далеко не элементарная (кстати как там элементарная — не значит несложная) задача.

TB>А вот смерть объекта раньше ожидаемого — попадалась.

Да, и мне попадалось и попадается такое в очень разных языках, когда ресурс оказывается мертвым, или же наоборот ресурс висит. лайфтайм аднака ресурсы и технологии. И, знаешь, наверное это каким-то образом можно посчитать. Завести статистику, градации сложности. Старость / используемость / цитируемость ... куча параметров языков, и сравнивать. Главное о параметрах договориться, и можно сравнивать и прочее )) а так просто о чем говорить? Что на нете, хацкеле, и прочих нет bottle neck ? Просто, как бы мы обсуждаем язык со своей уже success story. А победителей не расстреливают ))
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[15]: Правомерно ли такое
От: T4r4sB Россия  
Дата: 27.08.20 22:28
Оценка:
Здравствуйте, ollv, Вы писали:

O> А вот я не сказал бы. Особенно, если на рекурсивном движке построены нетривиальные вычисления, это далеко не элементарная (кстати как там элементарная — не значит несложная) задача.


{} вокруг foo

O> Да, и мне попадалось и попадается такое в очень разных языках, когда ресурс оказывается мертвым, или же наоборот ресурс висит. лайфтайм аднака ресурсы и технологии.


Я про стековые объекты

O> Просто, как бы мы обсуждаем язык со своей уже success story. А победителей не расстреливают ))


Кобол, Паладин, С++...
Re[4]: Правомерно ли такое
От: Шахтер Интернет  
Дата: 29.08.20 21:48
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Здравствуйте, Шахтер, Вы писали:



Ш>>Нет. Возвращаемое значение должно быть rvalue.


Ш>>Коряво.


W>Коряво? Криво? Легко использовать неверно в другом контексте?

W>Вот с этим можно согласится.
W>А то, что "возвращаемое значение должно быть rvalue" — это выдумка. Нет такого требования, конечно же

ТС хотел сделать

inline
std::vector<int> makeVec( int i )
{
  std::vector<int> ret;

  ret.push_back(i);

  return ret;
}


Только записать в одну строку. Здесь хочется move в return. Для этого нужно rvalue.

inline
std::vector<int> makeVec( int i )
{
    return push_back_helper( std::vector<int>(), i );
}


Иначе будет копирование.

struct Vect
 {
  int val = 0 ;

  Vect() {}

  Vect(const Vect &obj) : val(obj.val) { Printf(Con,"copy\n"); }

  Vect(const Vect &&obj) : val(obj.val) { Printf(Con,"move\n"); }

  void push_back(int v) { val=v; }
 };

inline
Vect & push_back_helper( Vect &&v, int elem )
{
    v.push_back(elem);

    return v;
}

inline
Vect makeVec1( int i )
{
    Vect ret;

    ret.push_back(i);

    return ret;
}

inline
Vect makeVec2( int i )
{
    return push_back_helper(Vect(),i);
}

struct VectorInit : public Vect
 {
  template <class Func>
  VectorInit(Func func) { func((Vect &)*this); }
 };

/* Main() */

void Main()
 {
  {
   auto v = makeVec1( 3 );

   Printf(Con,"#;\n",v.val);
  }
  {
   auto v = makeVec2( 3 );

   Printf(Con,"#;\n",v.val);
  }
  {
   VectorInit v( [] (Vect &v) { v.push_back(3); } );

   Printf(Con,"#;\n",v.val);
  }
 }


Печатает

3
copy
3
3

В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.