Здравствуйте, vopl, Вы писали:
V>>>похоже, мы разговариваем на разных языках.. Причем тут оптимизатор — категорически не понимаю.
S>>Просто при том, что изначальный вопрос возник о том, что будет в результате применения оптимизации, конкретно NRVO.
V>аа.. я ориентировался на это
V>Выше приводил конкретные 5 пунктов, даже с косвенной отсылкой на стандарт, посредством которых мною допускается гипотеза сабжевого UB.
Простите, я скипну, поскольку эти 5 пунктов напоминают фокусы из категории "как математически доказать, что 2+2 равно 5". Вот так и здесь люди надергают цитат из стандарта не потрудившись согласовать их друг с другом, а потом выводят вещи, которые не имеют смысла. Простите, если это звучит резко.
V>Не припомню чтобы в твою сторону что то осталось без ответа.
(и чуть выше по ветке). Тов.σ не смог продолжить разговор про отсутствие константности в конструкторе, а там это был, имхо, ключевой момент.
V>Это дело вкуса. Для меня, например, стандарт — это правила игры в язык C++. Если кто то хочет играть в игру на основе собственного понимания правил — пожалуйста, но стандарт — это источник первичного смысла в ней. Аналогично можно было бы сказать, что законы написаны для юристов, а потом недоумевать, почему мне штрафы сыпятся и почему меня в тюрьму сажают.
Нет. Законы должны быть донесены до потребителя в простой и, желательно, логичной форме. Тогда как юридические формулировки законов -- это особый стиль записи предназначенный для того, чтобы максимально исключить неоднозначность трактовки. Аналогично и в стандарте: стандарт должен быть таким, чтобы независимые разработчики компилятора смогли реализовать по стандарту одно и тоже.
У программистов, использующих C++, задача иная. По хорошему им в стандарт вообще не должно быть нужно заглядывать, разве что лишь в каких-то неоднозначных моментах.
Re[82]: Когда это наконец станет defined behavior?
σ>Вопрос с подвохом: что если происходит NRVO и result с xxx обозначают один и тот же объект. Он будет константным?
Какой-то здесь, право слово, фигней страдают, пытаясь найти некий гипотетический UB. Хотя с NRVO и получением константного объекта из неконстантного можно запросто наступить на несложные грабли:
Суть в том, что неконстантный объект сохраняет себя в реестре. Но, т.к. деструктор для него не вызывается, то из реестра этот объект не удаляется. Но указатель на объект остается валидным, т.к. объект преобразуется в константу в вызывающей функции. Однако, т.к. реестр хранит неконстантный указатель на константный объект, то через реестр мы получаем возможность поменять этот самый константный объект. Что, кмк, есть UB.
GCC-11 (g++ -std=c++17 -O2) на Ubuntu-22.04 выдает вполне ожидаемое:
add to registry: 0x7ffd9a0035b0
value: 42
consume_one: 42
consume_two: 142
removed from registry: 0x7ffd9a0035b0
Даже не пришлось на разные исходные файлы разбивать.
Re[104]: Когда это наконец станет defined behavior?
Здравствуйте, σ, Вы писали:
S>>>>Не поменяет, а приобретет.
σ>>>Ладно, спрошу как тебе угодно: каким образом приобретёт.
S>>Автоматически после завершения работы конструктора.
σ>Т.е при завершении работы конструктора меняется тип объекта?
При завершении работы конструктора в точке вызова как раз появляется объект, который уже будет константным.
Т.е. если у нас есть:
то в точке (1) сперва запускается конструктор для нового объекта. Внутри конструктора уже есть объект типа demo. Но это пока что не объект d внутри f, т.к. конструктор еще не завершил свою работу. А когда завершает, то в f появляется объект типа "const demo". Просто пока работал конструктор это был некий безымянный объект типа demo, а когда конструктор завершился он же стал именованным объектом d типа "const demo".
σ>Ладно. Я думал это понятно, но, видимо, придётся проговорить явно. Когда я спрашиваю про поведение программы на цепепе, меня интересуют определения стандарта, а не твои. Твои не интересуют.
Тут остается разве что поинтересоваться а чем ваше стремление увидеть цитату из стандарта отличается от "начетничества".
S>>>>Ну так там же и написано, что const на время работы конструктора на объект не распространяется.
σ>>>Написано, что const semantics не распространяется.
S>>И чтобы это могло значить? Ну, кроме того, что объект не константен.
σ>То, что константен, но модифицировать его (и даже его подобъекты) не UB.
Если что-то можно модифицировать (и это не mutable поле), то это не константа. Смысл константности в том, что изменять это нельзя.
Но если для вас смысл константности в том, что в стандарте написано, что константой считается то, что объявлено как const, то здесь остается только развести руками.
σ>Может покажешь в стандарте про смену типа объекта при возврате из конструктора?
Нет.
σ>Если ты про область видимости переменных s и t,
Нет, не про область видимости.
σ>
struct S { int i; };
σ>S f();
σ>const S t = f();
σ>S f()
σ>{
σ> S s;
σ> s.i = 0;
σ> return s;
σ>}
σ>то вот, внутри функции s и t доступны "одновременно".
Нет.
Более того, если вы модифицируете свою f так, чтобы там было обращение к t, то вы получите UB.
Re[83]: Когда это наконец станет defined behavior?
Здравствуйте, so5team, Вы писали:
S>entity make_entity(entity_registry & registry) { S> entity ent{®istry};
S>Суть в том, что неконстантный объект сохраняет себя в реестре.
А всё потому, что нефиг ссылки на локалки сохранять во внешнем объекте.
Правда если бы не сработало РВО, то тупо локальный объект бы сам себя удалил из реестра.
Короче код на грани фола, и слово const тут его уже не спасает
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, vopl, Вы писали:
V>>Во первых, не вижу необходимости кому либо что то демонстрироать. Обрати внимание, я называю сабжевое UB "гипотетическим", "подозреваемым".
V>И какое неопределённое поведение тут может быть? V>Пусть даже самое гипотетическое?
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, vopl, Вы писали:
V>>Вероятно, это недоработка языка.
V>Или собственное непонимание, ведь стандарт описан не для домохозяек, а для специалистов с неким ненулевым бэкграундом.
у вас тут секта грубиянов чтоли?
Re[84]: Когда это наконец станет defined behavior?
Здравствуйте, T4r4sB, Вы писали:
TB>Правда если бы не сработало РВО, то тупо локальный объект бы сам себя удалил из реестра.
ВотЪ!
TB>Короче код на грани фола
На грани фола здесь то, что нет явно определенных пользователем конструкторов копирования/перемещения. Которые либо автоматически бы добавляли новый объект в реестр, либо же запрещали его изъятие из реестра в деструкторе. Впрочем, здесь это преднамеренно не проблема, т.к. попытка удаления из реестра объекта, который в реестре не зарегистрирован, заведомо безопасна.
Так что в целом с дизайном entity и entity_registry все более-менее ОК для маленького демонстрационного примера.
TB>и слово const тут его уже не спасает
А оно и не может.
Re[101]: Когда это наконец станет defined behavior?
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, vopl, Вы писали:
V>>>>похоже, мы разговариваем на разных языках.. Причем тут оптимизатор — категорически не понимаю.
S>>>Просто при том, что изначальный вопрос возник о том, что будет в результате применения оптимизации, конкретно NRVO.
V>>аа.. я ориентировался на это
однозначно свзяываешь NRVO и оптимизацию? Это не так, NRVO может иметь место и без оптимизации, оптимизация может не применить NRVO.
V>>Выше приводил конкретные 5 пунктов, даже с косвенной отсылкой на стандарт, посредством которых мною допускается гипотеза сабжевого UB.
S>Простите, я скипну, поскольку эти 5 пунктов напоминают фокусы из категории "как математически доказать, что 2+2 равно 5". Вот так и здесь люди надергают цитат из стандарта не потрудившись согласовать их друг с другом, а потом выводят вещи, которые не имеют смысла. Простите, если это звучит резко.
К сожалению, это все голословно. Вот если бы ты показал в этих пунктах ошибку, которая покажет несостоятельность сделанного вывода..
V>>Не припомню чтобы в твою сторону что то осталось без ответа.
S>Зато я помню (точнее, могу найти т.к. здесь все ходы записаны): http://rsdn.org/forum/cpp/8583454.1
(и чуть выше по ветке). Тов.σ не смог продолжить разговор про отсутствие константности в конструкторе, а там это был, имхо, ключевой момент.
Ухты пухты. Я не отвечаю за тов. σ, я отвечаю только за себя.
V>>Это дело вкуса. Для меня, например, стандарт — это правила игры в язык C++. Если кто то хочет играть в игру на основе собственного понимания правил — пожалуйста, но стандарт — это источник первичного смысла в ней. Аналогично можно было бы сказать, что законы написаны для юристов, а потом недоумевать, почему мне штрафы сыпятся и почему меня в тюрьму сажают.
S>Нет. Законы должны быть донесены до потребителя в простой и, желательно, логичной форме. Тогда как юридические формулировки законов -- это особый стиль записи предназначенный для того, чтобы максимально исключить неоднозначность трактовки. Аналогично и в стандарте: стандарт должен быть таким, чтобы независимые разработчики компилятора смогли реализовать по стандарту одно и тоже.
S>У программистов, использующих C++, задача иная. По хорошему им в стандарт вообще не должно быть нужно заглядывать, разве что лишь в каких-то неоднозначных моментах.
Услышал твое мнение/позицию, ок.
Re[85]: Когда это наконец станет defined behavior?
Здравствуйте, so5team
S>На грани фола здесь то, что нет явно определенных пользователем конструкторов копирования/перемещения.
Использование мув конструктора чтоб фиксить ссылки в реестре — ну это допустимо по правилам цпп, но по мне так это полная дичь, и тащить это в язык я б не стал. Необходимость думать про такие случаи тяжелым крестом лежит на плечах крестокомпилятора, изза чего он даже не может передать юник в регистрах, или реаллоцировать вектор простым realloc.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[102]: Когда это наконец станет defined behavior?
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, vopl, Вы писали:
V>>вот тут внимательно посмотри V>>в исходном примере имеем const std::map<int, int> someDictionary = buildMap(); V>>в развертке же ссылка
V>Которой по-факту не существует — под неё не выделяется память. V>Прямо по стандарту компилятору позволяется рассматривать такую ссылку как алиас другой переменной, если ссылка инициализируется именно так — в области видимости ссылаемой переменной/значения.
Не на то смотришь. V>>в исходном примере имеем const std::map<int, int> someDictionary = buildMap();
то есть, имеет место декларация имени someDictionary и объекта типа const std::map<int, int>
V>>в развертке же ссылка
снова декларация имени someDictionary (это не важно) НО теперь совершенно другого объекта (он имеет уже ссылочноый тип и связывается с тем первичным объектом, но это тоже не важно)
то есть, тот первичный объект никак не определяется в этом месте. Соответственно, не получает тип const std::map<int, int>
вот в этом и есть разница. В исходном примере он получил тип const std::map<int, int> а в "развертке" от so5team — не получил.
моя дальнейшая логика будет строиться на этом различии. В чем я тут ошибаюсь?
Re[102]: Когда это наконец станет defined behavior?
, после слов "почему тут подозревается UB:" 5 пунктов разъясняющих гипотетическое UB
Тебе на это уже отвечали:
Это так не работает, реально. ))
Абсолютно любое потенциальное UB из стандарта может быть достаточно легко объяснено "на пальцах" — откуда может взяться расхождение описанного в коде и реально происходящего.
Конкретно в этой ситуации лично я не вижу потенциального UB, которое можно было бы разумно объяснить.
(оговорку про использование неинициализированных глобальных переменных сделал сразу же, но эта оговорка справедлива к любым таким переменным, необязательно константным)
В итоге, ни ты, ни твой союзник не показали сути этого потенциального UB, кроме как через малосвязанные пункты из стандарта, где эту связь вы насосали из пальца.
Суть вашего насоса вам сразу же сообщили и даже показали в "развёртке" — ссылание на объект неодновременно, а подразумеваемый вами UB должен случиться при одновременном наличии константной и неконстантной отсылки к объекту.
V>5. следовательно, модификация s.i = 0 подозревается в UB
Никаких "следовательно", бо константного объекта еще не существует, отсылка к нему невалидна, т.к. сам объект еще не создан.
В любом случае, это не ответ на заданный вопрос — в чём именно заключается UB???
Для ответа на этот вопрос следует не ссылаться на стандарт, а ровно наоборот — брать упоминание UB из стандарта и пояснить своё понимание — каким образом в той или иной ситуации возникает неопределённое поведение в терминах происходящего в вычислительной модели С++ в рантайме.
Вот пример объяснения UB, возникающего из хака константности, на который вы ссылаетесь:
Разница есть в системе допущений, которыми вправе пользоваться компилятор в процессе оптимизации, например, не запрашивать некие поля или не вычислять некие значения от полей объекта повторно. Т.е. потенциальное UB возможно из-за неверных этих допущений, если горе-программист хакнул собственный константный объект, радостно обманув глупый компилятор.
Итого, просьба породить пример, который избегает UB по глобальной инициализации, но потенциально содержит UB по "хаку" константности, при этом необходимо указать не пункт стандарта, а объяснить суть потенциального UB (даже если оно не наблюдается в мейнстримовых актуальных компиляторах).
Здравствуйте, vdimas, Вы писали:
V>Кстате, в исходном примере можно было переделать на ссылку, чтобы ты по мелочам не придирался: V>
V>const std::map<int, int> & map = buildMap();
V>
V>И ничего не изменится, после всех оптимизаций (просто в этом случае будет одна оптимизация копирования, а не две, как в исходном примере).
В этом случае изменится весь кейс. Пропадет NRVO, пропадет вторая декларация "того же самого объекта", пропадает его константность, пропадает "модификация константного объекта", пропадает то "гипотетическое UB".
Re[102]: Когда это наконец станет defined behavior?
Здравствуйте, vopl, Вы писали:
S>>>>Просто при том, что изначальный вопрос возник о том, что будет в результате применения оптимизации, конкретно NRVO.
V>>>аа.. я ориентировался на это
Так там прямо из названия следует: Named Return Value Optimization.
Если что-то называется "оптимизацией", да и ведет себя как "оптимизация", то это оптимизация и есть.
V>Это не так, NRVO может иметь место и без оптимизации, оптимизация может не применить NRVO.
Правильно ли я понимаю, что для вас оптимизация -- это когда флаги компилятору вроде -O1 или -O2 передаются?
Так-то компилятор может проводить оптимизации (т.е. устранять избыточный код) и без этих самых флагов, AFAIK.
S>>Простите, я скипну, поскольку эти 5 пунктов напоминают фокусы из категории "как математически доказать, что 2+2 равно 5". Вот так и здесь люди надергают цитат из стандарта не потрудившись согласовать их друг с другом, а потом выводят вещи, которые не имеют смысла. Простите, если это звучит резко.
V>К сожалению, это все голословно. Вот если бы ты показал в этих пунктах ошибку, которая покажет несостоятельность сделанного вывода..
Так тут уже много-много раз пытались. Вы хотите еще один подход?
Чтож, давайте попробуем. Подозрение в наличии UB у некоторых возникает из-за того, что они думают, что константный объект сперва появляется в вызывающей функции, затем модифицируется в вызываемой. И, т.к. в вызывающей функции он константен, то в вызываемой происходит модификация константного объекта.
Однако, людям, которые страдают этим подозрением следовало бы доказать и себе, и всем окружающим, что константный объект сперва появляется в вызывающей функции. И что лишь потом к нему обращается вызываемая. А это, мягко говоря, неочевидно.
Следовательно, пока не доказано что константный объект начал жить раньше, чем была вызвана функция, мы имеем неконстантный объект внутри вызванной функции. А раз он неконстантный, то его модификация не UB. Потом, в силу NRVO, этот объект не умирает, а остается жить внутри вызывающей функции, но уже как константный. Т.е. константный объект физически появляется в вызывающей функции только после завершения работы вызванной.
Поскольку я не знаток стандарта, то подтвердить цитатами все это не смогу. Да и вроде незачем, т.к. УМВР
Re[86]: Когда это наконец станет defined behavior?
Здравствуйте, T4r4sB, Вы писали:
S>>На грани фола здесь то, что нет явно определенных пользователем конструкторов копирования/перемещения.
TB>Использование мув конструктора чтоб фиксить ссылки в реестре — ну это допустимо по правилам цпп, но по мне так это полная дичь
Конкретно в этом случае смысл move-конструктора/оператора далеко не очевиден. Если внутри entity нет каких-то тяжелых данных, то по-хорошему, для такой ситуации move-конструктор/оператор вообще следовало бы запретить.
Re[100]: Когда это наконец станет defined behavior?
Здравствуйте, vopl, Вы писали:
V>>Прямо по стандарту компилятору позволяется рассматривать такую ссылку как алиас другой переменной, если ссылка инициализируется именно так — в области видимости ссылаемой переменной/значения. V>Не на то смотришь.
Наоборот, заставляю тебя смотреть "на то", бо ниже ты опять косячишь в рассуждениях — продолжаем ликбез! ))
V>>>в исходном примере имеем const std::map<int, int> someDictionary = buildMap(); V>то есть, имеет место декларация имени someDictionary и объекта типа const std::map<int, int>
Не бывает декларации объекта. ))
Тут декларация переменной обычного (не ссылочного) типа, т.е. введение строкового идентификатора для алиаса численного адреса некоего значения.
V>>>в развертке же ссылка V>снова декларация имени someDictionary (это не важно) НО теперь совершенно другого объекта (он имеет уже ссылочноый тип и связывается с тем первичным объектом, но это тоже не важно)
Потому что захватить для владения временный объект я могу только по константной ссылке, т.е. после захвата этого значения оно превращается в константное — к типу значения добавляется соотв. модификатор. И теперь без хака-реинтерпретации памяти ты эту константность никак не нарушишь.
В итоге, компилятор породит идентичный код для случая возврата в переменную по значению и для случая захвата временного объекта по ссылке прямо согласно стандарта, где компилятор имеет право не создавать переменную-ссылку, если алиасинг происходит в области видимости захватываемого ссылкой значения.
Т.е. ссылка будет использоваться в точности как идентификатор-алиас локального адреса данных, отсюда и порождаемый код будет идентичным.
V>то есть, тот первичный объект никак не определяется в этом месте.
Локальный еще как определяется, причём строго и непротиворечиво — просто он безымянный/временный, это результат вызова buldMap().
Но для него точно так же прописано время его жизни в данном scope.
V>Соответственно, не получает тип const std::map<int, int>
Получает этот тип при захвате владения временным объектом через константную ссылку.
V>вот в этом и есть разница.
Это у тебя от непонимания организации времени жизни временных объектов.
V>В исходном примере он получил тип const std::map<int, int> а в "развертке" от so5team — не получил.
На это уже отвечал — в исходном примере можно было изменить на const std::map<int, int> &, и ничего бы не изменилось.
Просто кто же знал, что ты плаваешь еще и в этом ? ))
V>моя дальнейшая логика будет строиться на этом различии. В чем я тут ошибаюсь?
Сразу в нескольких вещах:
1. Непонимание, что есть "переменная".
2. Непонимание алиасинга ссылок времени компиляции (необязательность выделения памяти под переменные-ссылки).
3. Непонимание времени жизни временных безымянных значений, где без продления времени жизни временных значений через константную ссылку, время жизни временного значения отдаётся на откуп компилятору — либо в текущей области видимости, либо в рамках текущего выражения, породившего временное безымянное значение.
4. Непонимание записи вида const T obj = T(42);, где компилятор вправе исключить создание временного объекта согласно предыдущего пункта, т.е. исключить вызов конструктора копирования, хотя, согласно семантике, происходит именно это (копирование временного значения), и для успешной компиляции требуется доступность как конструктора T(int) для создания временного значения, так и конструктора T(const T &) для копирования временного значения в инициализируемую переменную, т.е. в этом выражении во время компиляции используются оба конструктора, хотя в бинарнике останется вызов только T(int).
Здравствуйте, vopl, Вы писали:
V>Здравствуйте, vdimas, Вы писали:
V>>Кстате, в исходном примере можно было переделать на ссылку, чтобы ты по мелочам не придирался: V>>
V>>И ничего не изменится, после всех оптимизаций (просто в этом случае будет одна оптимизация копирования, а не две, как в исходном примере).
V>В этом случае изменится весь кейс.
Не-а.
V>Пропадет NRVO
А почему бы тебе, вместо сотрясения воздуха, предварительно не проверить самостоятельно — пропадается ли NRVO или нет? ))
V>пропадет вторая декларация "того же самого объекта"
Остаётся.
Безымянное/временное значение — такое же "честное" значение, как и локальная переменная, это значение можно захватить для владения в текущем scope.
V>пропадает его константность
Константность не может пропасть, согласно правилам С++ константность можно только добавить.
Обратное будет хаком. ))
V>пропадает "модификация константного объекта", пропадает то "гипотетическое UB".
Если бы вы были в состоянии пояснить суть UB (а не просто ссылаться на стандарт), вы бы увидели, что кейзы равнозначны.
Суть в том, что компилятор не по каждому константному объекту делает некие допущения и соотв.оптимизации, а только когда видит его жизненный цикл.
Т.е. подать константную ссылку извне в ф-ию, или получить константную ссылку на локальное временное значение — две большие разницы.
Во втором случае компилятор рассматривает локальное временное значение как имеющее алиасинг, т.е. в точности так же, как он рассматривал бы локальную константную переменную, куда поместили бы это значение.
S>то в точке (1) сперва запускается конструктор для нового объекта. Внутри конструктора уже есть объект типа demo. Но это пока что не объект d внутри f, т.к. конструктор еще не завершил свою работу. А когда завершает, то в f появляется объект типа "const demo". Просто пока работал конструктор это был некий безымянный объект типа demo, а когда конструктор завершился он же стал именованным объектом d типа "const demo".
Не понел, в (1) два объекта, что ли?
S>Если что-то можно модифицировать (и это не mutable поле), то это не константа. Смысл константности в том, что изменять это нельзя.
Ок. А смысл const object — в другом. Меня интересует const object.
S>Более того, если вы модифицируете свою f так, чтобы там было обращение к t, то вы получите UB.
Можно конкретнее? Пример модификации и причина UB.
Re[106]: Когда это наконец станет defined behavior?
Здравствуйте, σ, Вы писали:
S>>При завершении работы конструктора в точке вызова как раз появляется объект, который уже будет константным.
σ>Что значит появляется?
Значит появляется. Объяснить эту вещь на еще более тривиальном уровне я не смогу, сорри.
S>>Т.е. если у нас есть: S>>
S>>то в точке (1) сперва запускается конструктор для нового объекта. Внутри конструктора уже есть объект типа demo. Но это пока что не объект d внутри f, т.к. конструктор еще не завершил свою работу. А когда завершает, то в f появляется объект типа "const demo". Просто пока работал конструктор это был некий безымянный объект типа demo, а когда конструктор завершился он же стал именованным объектом d типа "const demo".
σ>Не понел, в (1) два объекта, что ли?
Нет. Просто точка (1) она не точка, это временной отрезок, который начинается, длится и заканчивается. Когда он начинается в программе появляется объект типа demo для которого вызывается конструктор, когда этот отрезок завершается этот самый объект становится доступным внутри f() под именем d. Но пока этот отрезок не завершился, внутри f() объекта d еще нет (и может не появится, если конструктор demo бросит исключение или дернет std::abort), хотя место под d уже есть.
S>>Если что-то можно модифицировать (и это не mutable поле), то это не константа. Смысл константности в том, что изменять это нельзя.
σ>Ок. А смысл const object — в другом. Меня интересует const object.
Вы в очередной раз отсылаете к этому разделу стандарта. Но там не описан смысл константного объекта. Там дано определение того, что с точки зрения языка считается const object.
S>>Более того, если вы модифицируете свою f так, чтобы там было обращение к t, то вы получите UB.
σ>Можно конкретнее? Пример модификации и причина UB.
Конкретнее я вообще не говорил про модификацию, а про обращение (обращение не обязательно означает модификацию, чтение так же является обращением).
А пример, пожалуйста:
struct S { int i; };
S f();
const S t = f();
S f()
{
S s;
s.i = t.i + 42;
return s;
}
При первом вызове f(), который произойдет при инициализации t, вы получите UB, т.к. t не инициализирован, следовательно, вы обращаетесь к неинициализированному объекту, что есть UB, если меня окончательно не добил склероз.
Re[103]: Когда это наконец станет defined behavior?
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, vopl, Вы писали:
V>>>И какое неопределённое поведение тут может быть? V>>>Пусть даже самое гипотетическое? V>>тут
, после слов "почему тут подозревается UB:" 5 пунктов разъясняющих гипотетическое UB
V>Тебе на это уже отвечали: V>
V>Это так не работает, реально. ))
V>Абсолютно любое потенциальное UB из стандарта может быть достаточно легко объяснено "на пальцах" — откуда может взяться расхождение описанного в коде и реально происходящего.
V>Конкретно в этой ситуации лично я не вижу потенциального UB, которое можно было бы размуно объяснить.
V>(оговорку про использование неинициализированных глобальных переменных сделал сразу же, но эта оговорка справедлива к любым таким переменным, необязательно константным)
V>В итоге, ни ты, ни твой союзник не показали сути этого потенциального UB, кроме как через малосвязанные пункты из стандарта, где эту связь вы насосали из пальца.
ну, мнение услышал
V>Суть вашего насоса вам сразу же сообщили и даже показали в "развёртке" — ссылание на объект неодновременно, а подразумеваемый вами UB должен случиться при одновременном наличии константной и неконстантной отсылки к объекту.
ну так там оно и есть все "одновременно". Константный объект, используемый сквозь неконстантное имя, подвергается модификации. Каким образом объект является константным я показал, ты опровер это доводом "это так не работает" и "лично я не вижу", у меня против таких опровержений — доводов нет, тут сливаюсь
V>>5. следовательно, модификация s.i = 0 подозревается в UB V>Никаких "следовательно", бо константного объекта еще не существует, отсылка к нему невалидна, т.к. сам объект еще не создан.
в случае NRVO объект внутри и снаружи — это один и тот же объект (σ приводил ссылку на стандарт), следовательно его время жизни уже началось, он уже создан. Тип этого объекта опледеляется декларацией, коих две штуки и в одной из них он объявлен как константный, то есть, имеются основания полагать что компилятор может его посчитать константным.
V>В любом случае, это не ответ на заданный вопрос — в чём именно заключается UB???
UB возможно исходя из факта модификации объекта, который гипотетически может быть трактован компилятором как константный, (σ приводил ссылку на стандарт)
V>Для ответа на этот вопрос следует не ссылаться на стандарт, а ровно наоборот — брать упоминание UB из стандарта и пояснить своё понимание — каким образом в той или иной ситуации возникает неопределённое поведение в терминах происходящего в вычислительной модели С++ в рантайме.
V>Вот пример объяснения UB, на который вы ссылаетесь: V>
V>Разница есть в системе допущений, которыми вправе пользоваться компилятор в процессе оптимизации, например, не запрашивать некие поля или не вычислять некие значения от полей объекта повторно. Т.е. потенциальное UB возможно из-за неверных этих допущений, если горе-программист хакнул собственный константный объект, радостно обманув глупый компилятор.
V>Итого, просьба породить пример, который избегает UB по глобальной инициализации, но потенциально содержит UB по "хаку" константности, при этом необходимо указать не пункт стандарта, а объяснить суть потенциального UB (даже если оно не наблюдается в мейнстримовых актуальных компиляторах).
V>Не сможете пояснить суть UB — слили.
давай изначально считать что я слил. Мне интересно разобраться в вопросе а не поэмоционировать
суть UB в том что компилятор на основе константности может сделать допущения, являющиеся ошибочными так как объект используется как не константный. И такие ошибочные допущения могут привести к аномалиям, например:
1. предположим, компилятор таки посчитал объект константным в силу той второй декларации где он имеет константный тип
2. для такого константного объекта компилятор может сделать допущение о том что после его конструирования (внутри функции) его состояние не меняется, следовательно можно упразднить все повторные загрузки из памяти этого состояния (они потребуются при вызове методов объекта внутри функции)
3. при отсутствии повторных загрузок — получаем коррупцию представления состояния объекта. Это негативный эффект от сабжевого UB