Re[102]: Когда это наконец станет defined behavior?
От: vdimas Россия  
Дата: 22.08.23 08:34
Оценка:
Здравствуйте, vopl, Вы писали:

V>>Или собственное непонимание, ведь стандарт описан не для домохозяек, а для специалистов с неким ненулевым бэкграундом.

V>у вас тут секта грубиянов чтоли?

Дык, вы ж не показали понимание прочитанного в стандарте.

Давай я покажу тебе суть того UB, на который вы ссылаетесь, где этот UB можно получить безо-всяких реинтерпретаций/хаков:
#include <vector>
#include <iostream>

class SomeObj;

class Registrar {
    std::vector<SomeObj*> regs_;
    int index {};

public:
    void registerObj(SomeObj * obj);
    void incrementAll();
};

class SomeObj {
public:
    SomeObj(Registrar & reg) {
        reg.registerObj(this);
    }

    int index {};
};

void Registrar::registerObj(SomeObj * obj) {
    obj->index = index++;
    regs_.push_back(obj);
}

void Registrar::incrementAll() {
    for(auto * obj : regs_)
        obj->index++;
}

Registrar registrar;

int main() {
    const SomeObj obj1 = SomeObj(registrar);
    const SomeObj obj2 = SomeObj(registrar);
    std::cout << obj1.index << ", " << obj2.index << std::endl;

    registrar.incrementAll();
    std::cout << obj1.index << ", " << obj2.index << std::endl;
}


Из конструктора SomeObj протекла неконстантная отсылка к this.
Выведет:
0, 1
1, 2


До С++17 некоторые компиляторы падают во время исполнения, некоторые выдают мусор. ))
Re[103]: Когда это наконец станет defined behavior?
От: vopl Россия  
Дата: 22.08.23 08:42
Оценка:
Здравствуйте, so5team, Вы писали:

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


S>>>>>Просто при том, что изначальный вопрос возник о том, что будет в результате применения оптимизации, конкретно NRVO.


V>>>>аа.. я ориентировался на это
Автор: σ
Дата: 16.08.23


S>>>Так там про NRVO прямым текстом:

что если происходит NRVO


V>>однозначно свзяываешь NRVO и оптимизацию?


S>Так там прямо из названия следует: Named Return Value Optimization.

S>Если что-то называется "оптимизацией", да и ведет себя как "оптимизация", то это оптимизация и есть.

Ну, хз, меня субъективное жонглирование словами не убеждает. Выше по ветке это уже проходили, там implicit create позиционировался как не имеющий отношения к create..

V>>Это не так, NRVO может иметь место и без оптимизации, оптимизация может не применить NRVO.


S>Правильно ли я понимаю, что для вас оптимизация -- это когда флаги компилятору вроде -O1 или -O2 передаются?

S>Так-то компилятор может проводить оптимизации (т.е. устранять избыточный код) и без этих самых флагов, AFAIK.

не то что "для меня", но в том контексте где ты первый раз употребил это слово — я понял именно так, что под "оптимизатором" ты подразумевал ту штуковину, которая существенно преобразует программу всякими разными многочисленными способами с целью увеличения ее оптимальности, то есть, да, "это когда флаги компилятору вроде -O1 или -O2 передаются". Если не правильно понял — пардон, посыпаю голову пеплом.

S>>>Простите, я скипну, поскольку эти 5 пунктов напоминают фокусы из категории "как математически доказать, что 2+2 равно 5". Вот так и здесь люди надергают цитат из стандарта не потрудившись согласовать их друг с другом, а потом выводят вещи, которые не имеют смысла. Простите, если это звучит резко.


V>>К сожалению, это все голословно. Вот если бы ты показал в этих пунктах ошибку, которая покажет несостоятельность сделанного вывода..


S>Так тут уже много-много раз пытались. Вы хотите еще один подход?


S>Чтож, давайте попробуем. Подозрение в наличии UB у некоторых возникает из-за того, что они думают, что константный объект сперва появляется в вызывающей функции, затем модифицируется в вызываемой. И, т.к. в вызывающей функции он константен, то в вызываемой происходит модификация константного объекта.


Нет. Никаких "сперва". Константный объект снаружи и не-константный объект внутри, в случае NRVO это "один и тот же объект" (да, звучит как коллизия, но все же, так написано в стандарте). То есть, наружный константный объект модифицируется внутри функции через неконстантное имя. Это все есть одновременно, а не "сначала/затем"

S>Однако, людям, которые страдают этим подозрением следовало бы доказать и себе, и всем окружающим, что константный объект сперва появляется в вызывающей функции. И что лишь потом к нему обращается вызываемая. А это, мягко говоря, неочевидно.


Вот эта посылка не верна. Объект снаружи и внутри — это по стандарту "один и тот же объект". Его время жизни стартует внутри функции после отработки конструктора. После этого он одновременно и является константным (потому что снаружи задекларирован так) и модифицируется внутри функции.

S>Следовательно, пока не доказано что константный объект начал жить раньше, чем была вызвана функция, мы имеем неконстантный объект внутри вызванной функции. А раз он неконстантный, то его модификация не UB. Потом, в силу NRVO, этот объект не умирает, а остается жить внутри вызывающей функции, но уже как константный. Т.е. константный объект физически появляется в вызывающей функции только после завершения работы вызванной.


S>Поскольку я не знаток стандарта, то подтвердить цитатами все это не смогу. Да и вроде незачем, т.к. УМВР


Если УМВР то и предмета к обсуждению нет)
Re[107]: Когда это наконец станет defined behavior?
От: σ  
Дата: 22.08.23 08:43
Оценка:
S>>>При завершении работы конструктора в точке вызова как раз появляется объект, который уже будет константным.

σ>>Что значит появляется?


S>Значит появляется. Объяснить эту вещь на еще более тривиальном уровне я не смогу, сорри.


А кто просил на ещё более тривиальном уровне? Объясняй на более корректном.

σ>>Не понел, в (1) два объекта, что ли?


S>Нет. Просто точка (1) она не точка, это временной отрезок, который начинается, длится и заканчивается. Когда он начинается в программе появляется объект типа demo


Пруф можно?

S>для которого вызывается конструктор, когда этот отрезок завершается этот самый объект становится доступным внутри f() под именем d. Но пока этот отрезок не завершился, внутри f() объекта d еще нет


В смысле, переменная d не связана ещё ни с каким объектом, или что?

S>>>Если что-то можно модифицировать (и это не mutable поле), то это не константа. Смысл константности в том, что изменять это нельзя.


σ>>Ок. А смысл const object — в другом. Меня интересует const object.


S>Вы в очередной раз отсылаете к этому разделу стандарта. Но там не описан смысл константного объекта.


Что такое "смысл"? Про то, что (и когда) можно/нельзя делать с const object, я тоже ссылки давал.

S>Там дано определение того, что с точки зрения языка считается const object.


Да ладно!

S>>>Более того, если вы модифицируете свою f так, чтобы там было обращение к t, то вы получите UB.


σ>>Можно конкретнее? Пример модификации и причина UB.


S>Конкретнее я вообще не говорил про модификацию


И это при том, что парой строк выше процитировано «если вы модифицируете свою f»

S>А пример, пожалуйста:

S>
struct S { int i; };

S f();

const S t = f();

S f()
{
  S s;

  s.i = t.i + 42;

  return s;
}


S>При первом вызове f(), который произойдет при инициализации t, вы получите UB, т.к. t не инициализирован


Мы вроде случай NRVO обсуждаем, инициализация кончилась в S s;. Или нет?

S> следовательно, вы обращаетесь к неинициализированному объекту, что есть UB, если меня окончательно не добил склероз.
Re[108]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 22.08.23 08:53
Оценка:
Здравствуйте, σ, Вы писали:

S>>>>При завершении работы конструктора в точке вызова как раз появляется объект, который уже будет константным.


σ>>>Что значит появляется?


S>>Значит появляется. Объяснить эту вещь на еще более тривиальном уровне я не смогу, сорри.


σ>А кто просил на ещё более тривиальном уровне? Объясняй на более корректном.


Корректней некуда. Если вы понимаете только цитаты из стандарта, то, вероятно, вам нужно вот эти пункты (https://timsong-cpp.github.io/cppwp/n4868/basic.life):

The lifetime of an object of type T begins when:
(1.1) storage with the proper alignment and size for type T is obtained, and
(1.2) its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),


Т.е. момент, когда "lifetime" уже "begins".

И да, помнится вы спрашивали меня про что-то вроде "это критерии создания объекта". Вот, пожалуй, и ответ. Вроде бы я и не ошибся.

σ>>>Не понел, в (1) два объекта, что ли?


S>>Нет. Просто точка (1) она не точка, это временной отрезок, который начинается, длится и заканчивается. Когда он начинается в программе появляется объект типа demo


σ>Пруф можно?


Пруф на что? На здравый смысл?

S>>для которого вызывается конструктор, когда этот отрезок завершается этот самый объект становится доступным внутри f() под именем d. Но пока этот отрезок не завершился, внутри f() объекта d еще нет


σ>В смысле, переменная d не связана ещё ни с каким объектом, или что?


В смысле что самого понятия d не существует пока инициализация d не завершена. При этом сам объект, который при удачном раскладе станет этим d, уже есть. В некотором промежуточном состоянии. Вот еще одна цитата по приведенной выше ссылке:

[Note 2: In particular, before the lifetime of an object starts and after its lifetime ends there are significant restrictions on the use of the object, as described below, in [class.base.init] and in [class.cdtor]. Also, the behavior of an object under construction and destruction might not be the same as the behavior of an object whose lifetime has started and not ended. [class.base.init] and [class.cdtor] describe the behavior of an object during its periods of construction and destruction. — end note]


S>>>>Если что-то можно модифицировать (и это не mutable поле), то это не константа. Смысл константности в том, что изменять это нельзя.


σ>>>Ок. А смысл const object — в другом. Меня интересует const object.


S>>Вы в очередной раз отсылаете к этому разделу стандарта. Но там не описан смысл константного объекта.


σ>Что такое "смысл"? Про то, что (и когда) можно/нельзя делать с const object, я тоже ссылки давал.


Я не видел таковых.

S>>Там дано определение того, что с точки зрения языка считается const object.


σ>Да ладно!


Представьте себе. Только это, не более.

S>>>>Более того, если вы модифицируете свою f так, чтобы там было обращение к t, то вы получите UB.


σ>>>Можно конкретнее? Пример модификации и причина UB.


S>>Конкретнее я вообще не говорил про модификацию


σ>И это при том, что парой строк выше процитировано «если вы модифицируете свою f»


Вы не отличаете модифицируете функцию f (т.е. изменение кода) от модификации объекта t?

S>>При первом вызове f(), который произойдет при инициализации t, вы получите UB, т.к. t не инициализирован


σ>Мы вроде случай NRVO обсуждаем, инициализация кончилась в S s;. Или нет?


Нет. Кончилась инициализация s внутри f. Инициализация t еще не начиналась.
Re[101]: Когда это наконец станет defined behavior?
От: vopl Россия  
Дата: 22.08.23 08:55
Оценка:
Здравствуйте, vdimas, Вы писали:

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


V>>>Прямо по стандарту компилятору позволяется рассматривать такую ссылку как алиас другой переменной, если ссылка инициализируется именно так — в области видимости ссылаемой переменной/значения.

V>>Не на то смотришь.

V>Наоборот, заставляю тебя смотреть "на то", бо ниже ты опять косячишь в рассуждениях — продолжаем ликбез! ))



V>>>>в исходном примере имеем const std::map<int, int> someDictionary = buildMap();

V>>то есть, имеет место декларация имени someDictionary и объекта типа const std::map<int, int>

V>Не бывает декларации объекта. ))


https://timsong-cpp.github.io/cppwp/basic.def#1.sentence-1

A declaration may (re)introduce one or more names and/or entities into a translation unit.


https://timsong-cpp.github.io/cppwp/basic.pre#3

An entity is a value, object, reference, structured binding, function, enumerator, type, class member, bit-field, template, template specialization, namespace, or pack.


пример использования выражения "декларация объекта": https://timsong-cpp.github.io/cppwp/dcl.pre#def:declaration,object
Re[101]: Когда это наконец станет defined behavior?
От: vopl Россия  
Дата: 22.08.23 09:02
Оценка:
Здравствуйте, vdimas, Вы писали:

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


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


V>>>Кстате, в исходном примере можно было переделать на ссылку, чтобы ты по мелочам не придирался:

V>>>
V>>>const std::map<int, int> & map = buildMap();
V>>>

V>>>И ничего не изменится, после всех оптимизаций (просто в этом случае будет одна оптимизация копирования, а не две, как в исходном примере).

V>>В этом случае изменится весь кейс.


V>Не-а.



V>>Пропадет NRVO


V>Апочему бы тебе, вместо сотрясения воздуха, предварительно не проверить самостоятельно — пропадается ли NRVO или нет? ))


наверное ты прав, NRVO может и не пропасть. Возвращенный через NRVO объект будет временным, его время жизни продлится ссылкой.. Согласен


V>>пропадет вторая декларация "того же самого объекта"


V>Остаётся.


А вот тут уже никуда не "остается". Декларации объекта теперь нет, вместо объекта теперь декларируется ссылка. Декларация ссылки это не то же самое что декларация объекта так как по декларации объекта определяется его тип, а по декларации ссылки — нет.
Re[104]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 22.08.23 09:02
Оценка: +1
Здравствуйте, vopl, Вы писали:

V>>>однозначно свзяываешь NRVO и оптимизацию?


S>>Так там прямо из названия следует: Named Return Value Optimization.

S>>Если что-то называется "оптимизацией", да и ведет себя как "оптимизация", то это оптимизация и есть.

V>Ну, хз, меня субъективное жонглирование словами не убеждает.


Тут мне остается только повторить, что если что-то называется оптимизацией и ведет себя как оптимизация, так это она и есть.

V>Выше по ветке это уже проходили, там implicit create позиционировался как не имеющий отношения к create..


А он и не имеет. implicit create не создает объектов, он возвращает указатель на объект, для которого лайвтайм будет считаться начатым. Но созданием объектов implicit create не занимается.

V>Нет. Никаких "сперва". Константный объект снаружи и не-константный объект внутри, в случае NRVO это "один и тот же объект" (да, звучит как коллизия, но все же, так написано в стандарте).


Ага.

V>То есть, наружный константный объект модифицируется внутри функции через неконстантное имя. Это все есть одновременно, а не "сначала/затем"


А вот тут нет. Без "сначала" и "затем" нет смысла, мы уходим в слохастическую эквилибристику и споры о том, сколько ангелов уместятся на кончике иглы.

То, что это один и тот же объект не означает, что объект сперва создается в вызывающей функции.
Он как раз создается в вызываемой. Но, за счет NRVO, не умирает там, а продолжает жить в вызвавшей.

Вот и все.

V>Вот эта посылка не верна. Объект снаружи и внутри — это по стандарту "один и тот же объект". Его время жизни стартует внутри функции после отработки конструктора.


А теперь задумайтесь какого именно. И где этот конструктор вызван.

V>Если УМВР то и предмета к обсуждению нет)


Ну так я здесь стал задавать вопросы надеясь на то, что мне с цитатами докажут как я был не прав. Но пока что выходит, что таки был прав
Re[104]: Когда это наконец станет defined behavior?
От: vdimas Россия  
Дата: 22.08.23 09:02
Оценка:
Здравствуйте, vopl, Вы писали:

V>ну так там оно и есть все "одновременно".


Только в случае глобальных переменных и только в случае доступа к переменным в фазе динамической инициализации модуля, где эта инициализация еще не завершена.
Это ДРУГОЕ UB. ))


V>Константный объект, используемый сквозь неконстантное имя, подвергается модификации.


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


V>в случае NRVO объект внутри и снаружи — это один и тот же объект (σ приводил ссылку на стандарт)


Но внешняя ссылка недоступна программе, т.е. компилятору негде внести неопределённое поведение.


V>следовательно его время жизни уже началось, он уже создан.


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

У данных, описанных в модуле, есть две фазы инициализации — статическая и динамическая.
В статической фазе происходит загрузка данных в сегмент данных из соотв.сегмента образа-бинарника.

В статической фазе инициализируются константы времени компиляции, например:
const int i = 42;

(туда же constexpr для вычислимых значений)

В динамической фазе происходит динамическая инициализация, например:
const int i = calcValue();

(если последняя несводима к constexpr)

Что характерно, в статической фазе константе const int i будет присвоено значение 0, а в динамической фазе эта константа будет перезаписана результатом вызова calValue(). Не смущает, ы? ))

То же самое касается конструкторов объектов, если эти конструкторы выполняются только динамически.

Так вот, услышьте уже, что доступ к неинициализированным данным модуля является UB и безо-всякого RVO/NRVO, т.е. это другое UB, нерелевантное обсуждаемому.
И тот якобы пример, который вы привели, он про UB вокруг динамической фазы инициализации. И об этом я сказал твоему союзнику с самого начала, бо вопрос не стоит и выеденного яйца, там всё слишком очевидно. ))

Но после динамической фазы инициализации модуля, либо же, в этой фазе, но с учётом гарантированной последовательности инициализации глобальных переменных модуля, можно избежать упомянутого мною UB, и RVO/NRVO опять на него никак не влияют. Всё.

Тут надо рассуждать не об RVO/NRVO, а об prvalue, которое, начиная с C++17 может не быть материализовано до момента необходимости.
См пример рядом:
http://www.rsdn.org/forum/cpp/8585549.1

Необязательность материализации prvalue — более общее допущение, которое способно даже удалять локальные промежуточные переменные, протягивая "сквозь них" prvalue в процессе оптимизации бинарника. Но! мы можем рассуждать исключительно и только о семантике, описанной в коде, как будто нет никаких допущений относительно необязательности материализации prvalue, нет никаких RVO/NRVO и прочих трюков. Именно поэтому для prvalue всё еще требуются конструкторы копирования, которых в конечном образе может и не быть за ненадобностью — они нужны исключительно для описания исходной семантики кода, которая гарантируется компилятором, с учётом замечания про побочные эффекты.

По ссылке приведён как раз побочный эффект конструктора, где this протекает "куда-то еще", в какой-то другой контекст, необнаруживаемый компилятором при компиляции текущего модуля.
(registrar по ссылке мог быть объявлен в другом модуле)
Re[103]: Когда это наконец станет defined behavior?
От: vopl Россия  
Дата: 22.08.23 09:10
Оценка:
Здравствуйте, vdimas, Вы писали:

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


V>>>Или собственное непонимание, ведь стандарт описан не для домохозяек, а для специалистов с неким ненулевым бэкграундом.

V>>у вас тут секта грубиянов чтоли?

V>Дык, вы ж не показали понимание прочитанного в стандарте.

Ну так это же не повод навешивать ярлыки. Если есть возможность — укажи на ошибку конкретно, я только благодарен буду

V>Давай я покажу тебе суть того UB, на который вы ссылаетесь, где этот UB можно получить безо-всяких реинтерпретаций/хаков:

V>
V>#include <vector>
V>#include <iostream>

V>class SomeObj;

V>class Registrar {
V>    std::vector<SomeObj*> regs_;
V>    int index {};

V>public:
V>    void registerObj(SomeObj * obj);
V>    void incrementAll();
V>};

V>class SomeObj {
V>public:
V>    SomeObj(Registrar & reg) {
V>        reg.registerObj(this);
V>    }

V>    int index {};
V>};

V>void Registrar::registerObj(SomeObj * obj) {
    obj->>index = index++;
V>    regs_.push_back(obj);
V>}

V>void Registrar::incrementAll() {
V>    for(auto * obj : regs_)
        obj->>index++;
V>}

V>Registrar registrar;

V>int main() {
V>    const SomeObj obj1 = SomeObj(registrar);
V>    const SomeObj obj2 = SomeObj(registrar);
V>    std::cout << obj1.index << ", " << obj2.index << std::endl;

V>    registrar.incrementAll();
V>    std::cout << obj1.index << ", " << obj2.index << std::endl;
V>}
V>


V>Из конструктора SomeObj протекла неконстантная отсылка к this.

V>Выведет:
V>
V>0, 1
V>1, 2
V>


V>До С++17 некоторые компиляторы падают во время исполнения, некоторые выдают мусор. ))


Эта суть понятна в полной мере. По прежнему имею мнение что сабжевый "гипотетический UB" имеет такую же природу, но несколько другой механизм активации
Re[100]: Когда это наконец станет defined behavior?
От: B0FEE664  
Дата: 22.08.23 09:26
Оценка: +2
Здравствуйте, σ, Вы писали:

σ>>>И что «lifetime»? Он начинается внутри функции, после инициализации result.

BFE>>Когда начинается lifetime объекта someDictionary ? Тогда, когда заканчивается конструирование объекта.
σ>Ну. При NRVO, оно заканчивается на std::map<int, int> result;.

Нет, конечно. Даже при NRVO вычисление значения выражения buildMap() должно быть выполнено до начала инициализации someDictionary. Это следует из описания sequenced before.
А пока вычисление выражения buildMap() не закончилось, время жизни константного объекта не началось:

The lifetime of an object of type T begins when: ... its initialization (if any) is complete

Запрет на модификацию константного объекта относится только ко времени жизни:

Any attempt to modify a const object during its lifetime results in undefined behavior.

Ну а так, как время жизни константного объекта ещё не началось, то изменять его можно.
Нет тут никакого UB.

BFE>>В выражении const std::map<int, int> someDictionary = buildMap(); вызов buildMap() sequenced before инициализации someDictionary, а значит значение для инициализации должно быть получено до начала lifetime объекта someDictionary. А до этих пор константный объект можно модифицировать.


σ>Получается, result.insert(42, 43); — UB, т.к. после старта лайфтайма?

Нет.
Такое впечатление, что вы не читает, что я пишу.

σ>Или объект сначала вроде как создаётся константным (const std::map<int, int> someDictionary), но потом становится неконстантным (std::map<int, int> result;), а опять константным не становится, и его можно менять даже после const std::map<int, int> someDictionary = buildMap();?

Близко нет.
И каждый день — без права на ошибку...
Re[109]: Когда это наконец станет defined behavior?
От: σ  
Дата: 22.08.23 09:27
Оценка:
S>>>>>При завершении работы конструктора в точке вызова как раз появляется объект, который уже будет константным.

σ>>>>Что значит появляется?


S>>>Значит появляется. Объяснить эту вещь на еще более тривиальном уровне я не смогу, сорри.


σ>>А кто просил на ещё более тривиальном уровне? Объясняй на более корректном.


S>Корректней некуда. Если вы понимаете только цитаты из стандарта, то, вероятно, вам нужно вот эти пункты (https://timsong-cpp.github.io/cppwp/n4868/basic.life):

S>

The lifetime of an object of type T begins when:
(1.1) storage with the proper alignment and size for type T is obtained, and
(1.2) its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),


S>Т.е. момент, когда "lifetime" уже "begins".


S>И да, помнится вы спрашивали меня про что-то вроде "это критерии создания объекта". Вот, пожалуй, и ответ. Вроде бы я и не ошибся.


Я тоже вижу что не ошибся в своих подозрениях что ты не знаешь разницы между созданием объекта и началом времени жизни объекта.
Параграф про lifetime start описывает как начинается lifetime уже существующего (созданного) объекта, а не про то, как объект создаётся.

σ>>>>Не понел, в (1) два объекта, что ли?


S>>>Нет. Просто точка (1) она не точка, это временной отрезок, который начинается, длится и заканчивается. Когда он начинается в программе появляется объект типа demo


σ>>Пруф можно?


S>Пруф на что? На здравый смысл?


Ну если ты хочешь переходить на такой детсадовский уровень, то ок: здравый смысл говорит что появляется объект типа const demo.

S>>>для которого вызывается конструктор, когда этот отрезок завершается этот самый объект становится доступным внутри f() под именем d. Но пока этот отрезок не завершился, внутри f() объекта d еще нет


σ>>В смысле, переменная d не связана ещё ни с каким объектом, или что?


S>В смысле что самого понятия d не существует пока инициализация d не завершена.


Что такое «самого понятия d не существует»? Ты можешь перестать выражаться всякими размытыми фразами? Что за «самоё понятие d»?

S>При этом сам объект, который при удачном раскладе станет этим d, уже есть. В некотором промежуточном состоянии. Вот еще одна цитата по приведенной выше ссылке:

S>

[Note 2: In particular, before the lifetime of an object starts and after its lifetime ends there are significant restrictions on the use of the object, as described below, in [class.base.init] and in [class.cdtor]. Also, the behavior of an object under construction and destruction might not be the same as the behavior of an object whose lifetime has started and not ended. [class.base.init] and [class.cdtor] describe the behavior of an object during its periods of construction and destruction. — end note]


И она тут к чему? В ней написано что-то про самоё понятие d?

S>>>>>Более того, если вы модифицируете свою f так, чтобы там было обращение к t, то вы получите UB.


σ>>>>Можно конкретнее? Пример модификации и причина UB.


S>>>Конкретнее я вообще не говорил про модификацию


σ>>И это при том, что парой строк выше процитировано «если вы модифицируете свою f»


S>Вы не отличаете модифицируете функцию f (т.е. изменение кода) от модификации объекта t?


Пора бы уже от выходных отойти. Или у тебя уже permanent damage?

S>>>При первом вызове f(), который произойдет при инициализации t, вы получите UB, т.к. t не инициализирован


σ>>Мы вроде случай NRVO обсуждаем, инициализация кончилась в S s;. Или нет?


S>Нет. Кончилась инициализация s внутри f. Инициализация t еще не начиналась.


Т.е. ты всё-таки не отличаешь объекты от переменных? Или что?
Re[105]: Когда это наконец станет defined behavior?
От: vopl Россия  
Дата: 22.08.23 09:37
Оценка: :)
Здравствуйте, so5team, Вы писали:

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


V>>>>однозначно свзяываешь NRVO и оптимизацию?


S>>>Так там прямо из названия следует: Named Return Value Optimization.

S>>>Если что-то называется "оптимизацией", да и ведет себя как "оптимизация", то это оптимизация и есть.

V>>Ну, хз, меня субъективное жонглирование словами не убеждает.


S>Тут мне остается только повторить, что если что-то называется оптимизацией и ведет себя как оптимизация, так это она и есть.


V>>Выше по ветке это уже проходили, там implicit create позиционировался как не имеющий отношения к create..


S>А он и не имеет. implicit create не создает объектов, он возвращает указатель на объект, для которого лайвтайм будет считаться начатым. Но созданием объектов implicit create не занимается.


https://timsong-cpp.github.io/cppwp/intro.object#1.sentence-2

An object is created by a definition, by a new-expression ([expr.new]), by an operation that implicitly creates objects (see below), when implicitly changing the active member of a union, or when a temporary object is created ([conv.rval], [class.temporary]).


например, operator new создает объект посредством этого самого implicitly creates
https://timsong-cpp.github.io/cppwp/intro.object#13.sentence-3

Any implicit or explicit invocation of a function named operator new or operator new[] implicitly creates objects in the returned region of storage and returns a pointer to a suitable created object.



V>>Нет. Никаких "сперва". Константный объект снаружи и не-константный объект внутри, в случае NRVO это "один и тот же объект" (да, звучит как коллизия, но все же, так написано в стандарте).


S>Ага.


V>>То есть, наружный константный объект модифицируется внутри функции через неконстантное имя. Это все есть одновременно, а не "сначала/затем"


S>А вот тут нет. Без "сначала" и "затем" нет смысла, мы уходим в слохастическую эквилибристику и споры о том, сколько ангелов уместятся на кончике иглы.

ангелы

S>То, что это один и тот же объект не означает, что объект сперва создается в вызывающей функции.

S>Он как раз создается в вызываемой. Но, за счет NRVO, не умирает там, а продолжает жить в вызвавшей.

S>Вот и все.


Именно так) Он создается в функции, затем просто продолжает жить вне ее после NRVO

V>>Вот эта посылка не верна. Объект снаружи и внутри — это по стандарту "один и тот же объект". Его время жизни стартует внутри функции после отработки конструктора.


S>А теперь задумайтесь какого именно. И где этот конструктор вызван.


Отработает конструктор не-константного типа, внутри функции

V>>Если УМВР то и предмета к обсуждению нет)


S>Ну так я здесь стал задавать вопросы надеясь на то, что мне с цитатами докажут как я был не прав. Но пока что выходит, что таки был прав


С цитатами — я приводил выше 5 пунктов, в них цитаты не прямо там вшиты, но есть отсылки к цитатам. Эти 5 пунктов все еще актуальны и не опровергнуты
Re[110]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 22.08.23 09:38
Оценка:
Здравствуйте, σ, Вы писали:

S>>Корректней некуда. Если вы понимаете только цитаты из стандарта, то, вероятно, вам нужно вот эти пункты (https://timsong-cpp.github.io/cppwp/n4868/basic.life):

S>>

The lifetime of an object of type T begins when:
σ>(1.1) storage with the proper alignment and size for type T is obtained, and
σ>(1.2) its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),


S>>Т.е. момент, когда "lifetime" уже "begins".


S>>И да, помнится вы спрашивали меня про что-то вроде "это критерии создания объекта". Вот, пожалуй, и ответ. Вроде бы я и не ошибся.


σ>Я тоже вижу что не ошибся в своих подозрениях что ты не знаешь разницы между созданием объекта и началом времени жизни объекта.

σ>Параграф про lifetime start описывает как начинается lifetime уже существующего (созданного) объекта, а не про то, как объект создаётся.

Замечательно, но пока вы оцениваете мои знания вы никаких доводов в пользу своей точки зрения не приводите.

σ>>>>>Не понел, в (1) два объекта, что ли?


S>>>>Нет. Просто точка (1) она не точка, это временной отрезок, который начинается, длится и заканчивается. Когда он начинается в программе появляется объект типа demo


σ>>>Пруф можно?


S>>Пруф на что? На здравый смысл?


σ>Ну если ты хочешь переходить на такой детсадовский уровень, то ок: здравый смысл говорит что появляется объект типа const demo.


Появляется. Не вижу здесь противоречий с тем, что я сказал. В чем предмет спора?

S>>>>для которого вызывается конструктор, когда этот отрезок завершается этот самый объект становится доступным внутри f() под именем d. Но пока этот отрезок не завершился, внутри f() объекта d еще нет


σ>>>В смысле, переменная d не связана ещё ни с каким объектом, или что?


S>>В смысле что самого понятия d не существует пока инициализация d не завершена.


σ>Что такое «самого понятия d не существует»? Ты можешь перестать выражаться всякими размытыми фразами? Что за «самоё понятие d»?


А вы попробуйте читать что вам пишут. У вас в коде есть строка:
void f() {
  const demo d;
  ...
}

Так вот, пользоваться d вы сможете только когда завершится его создание (т.е. выделение места и инициализация). До этого момента у вас в f() никакого d еще нет. Вот когда создание d завершится успешно, тогда d в f у вас есть. А до того нет. Вообще.

S>>При этом сам объект, который при удачном раскладе станет этим d, уже есть. В некотором промежуточном состоянии. Вот еще одна цитата по приведенной выше ссылке:

S>>

[Note 2: In particular, before the lifetime of an object starts and after its lifetime ends there are significant restrictions on the use of the object, as described below, in [class.base.init] and in [class.cdtor]. Also, the behavior of an object under construction and destruction might not be the same as the behavior of an object whose lifetime has started and not ended. [class.base.init] and [class.cdtor] describe the behavior of an object during its periods of construction and destruction. — end note]


σ>И она тут к чему? В ней написано что-то про самоё понятие d?


В ней написано про момент, когда объект уже "типа есть" но лайфтайм для него начатым еще не считается. А это как раз имеет прямое отношение к d, которого еще нет, пока его инициализация не завершилась (хотя объект типа demo уже конструируется и у него работает конструктор).

S>>>>>>Более того, если вы модифицируете свою f так, чтобы там было обращение к t, то вы получите UB.σ>>>Мы вроде случай NRVO обсуждаем, инициализация кончилась в S s;. Или нет?


S>>Нет. Кончилась инициализация s внутри f. Инициализация t еще не начиналась.


σ>Т.е. ты всё-таки не отличаешь объекты от переменных? Или что?


Вы хотите перейти на обсуждение персоналий? Или мы таки продолжим говорить про происходящее в C++?
Re[101]: Когда это наконец станет defined behavior?
От: σ  
Дата: 22.08.23 09:49
Оценка:
σ>>>>И что «lifetime»? Он начинается внутри функции, после инициализации result.
BFE>>>Когда начинается lifetime объекта someDictionary ? Тогда, когда заканчивается конструирование объекта.
σ>>Ну. При NRVO, оно заканчивается на std::map<int, int> result;.

BFE>Нет, конечно. Даже при NRVO вычисление значения выражения buildMap() должно быть выполнено до начала инициализации someDictionary. Это следует из описания sequenced before.


Да ради бога, пусть sequenced before.
Только вот sequenced before никак не отменят, что при NRVO someDictionary обозначает тот же объект, что и result, как описано в https://timsong-cpp.github.io/cppwp/n4868/class.copy.elision#1.sentence-2

BFE>А пока вычисление выражения buildMap() не закончилось, время жизни константного объекта не началось:

BFE>

The lifetime of an object of type T begins when: ... its initialization (if any) is complete


Ну и какая инициализация для этого объекта должа быть complete? Первая (std::map<int, int> result;) или последняя (которая для someDictionary)?

BFE>Запрет на модификацию константного объекта относится только ко времени жизни:

BFE>

Any attempt to modify a const object during its lifetime results in undefined behavior.

BFE>Ну а так, как время жизни константного объекта ещё не началось, то изменять его можно.
BFE>Нет тут никакого UB.

Раз время жизни объекта не началось, то result.insert(42, 43); — вызов метода на объекте до начала времени жизни? Тогда получается UB есть.

BFE>>>В выражении const std::map<int, int> someDictionary = buildMap(); вызов buildMap() sequenced before инициализации someDictionary, а значит значение для инициализации должно быть получено до начала lifetime объекта someDictionary. А до этих пор константный объект можно модифицировать.


σ>>Получается, result.insert(42, 43); — UB, т.к. после старта лайфтайма?

BFE>Нет.
BFE>Такое впечатление, что вы не читает, что я пишу.

Аналогично.

σ>>Или объект сначала вроде как создаётся константным (const std::map<int, int> someDictionary), но потом становится неконстантным (std::map<int, int> result;), а опять константным не становится, и его можно менять даже после const std::map<int, int> someDictionary = buildMap();?

BFE>Близко нет.
Ты наверное опечатался когда хотел написать «ближе нет»?
  Скрытый текст
По крайней мере кое-то в CWG согласен, что, видимо, согласно текущему тексту стандарта, такое описание самое (формально) корректное .
В общем, я спалил ответ на свой вопрос, по крайней мере соответствующий стандарту буквально (насколько стандарт тут дефектен, это отдельный разговор), а ты даже не понял.
Re[106]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 22.08.23 09:55
Оценка:
Здравствуйте, vopl, Вы писали:

V>>>Выше по ветке это уже проходили, там implicit create позиционировался как не имеющий отношения к create..


S>>А он и не имеет. implicit create не создает объектов, он возвращает указатель на объект, для которого лайвтайм будет считаться начатым. Но созданием объектов implicit create не занимается.


V>https://timsong-cpp.github.io/cppwp/intro.object#1.sentence-2

V>

An object is created by a definition, by a new-expression ([expr.new]), by an operation that implicitly creates objects (see below), when implicitly changing the active member of a union, or when a temporary object is created ([conv.rval], [class.temporary]).


Ну вот еще раз люди читают стандарт и теряют из виду смысл происходящего (это как за деревьями не видеть леса).

А смысл такой: в C++ объекты должны быть созданы (т.е. у них должен начаться lifetime) видимым для компилятора образом. Если появляется указатель на что-то, что компилятор не может определить как корректно созданный объект (с начатым lifetime), то компилятор волен сотворить разное. При этом в реальной жизни случаются ситуации, когда объекты создаются невидимым для компилятора образом (скажем, посредством вызова calloc, посредством чтения с диска в память или посредством отображения из разделяемой памяти). И тогда возникает вопрос как указать компилятору, что у нас корректный объект, а не херня какая-то.

И вот для решения этой проблемы (причем в большей степени для решения проблемы того, как описать это в стандарте) и сделали термин implicitly creates. Т.е. применение некоторых конструкций (вроде каста возвращенного calloc-ом результата к указателю на некий T) якобы создает объект типа T.

Хотя, на самом деле, здесь нет никакого создания. Создание (а именно выделение места и инициализация этого места должным образом) лежит на пользователе. Т.е., по факту, implicitly creates означает, что пользователь сделал все вручную, но затем компилятор согласился считать полученный пользователем указатель валидным указателем на объект с начатым lifetime.

Вот, собственно, и все.

Именно так и следует объяснять происходящее обычным разработчикам. Чтобы они понимали, что создание объекта через new -- это одно. Создание объекта на стеке -- другое. Легитимизация указателя на содержимое объекта полученное через разделяемую память -- третье. Хотя с точки зрения текста стандарта это все типа "creates".

Вот если бы происходящее в языке C++ объясняли такими простыми словами, лично моя жизнь была бы сильно проще.

S>>Вот и все.


V>Именно так) Он создается в функции, затем просто продолжает жить вне ее после NRVO


Если вы согласны с этим, то у вас просто нет константного объекта, который начал жить раньше и который мы якобы пытаемся модифицировать внутри. Т.е. и нет предмета для спора.

V>С цитатами — я приводил выше 5 пунктов, в них цитаты не прямо там вшиты, но есть отсылки к цитатам. Эти 5 пунктов все еще актуальны и не опровергнуты


Еще раз повторюсь про аналогию с доказательством что 2+2=5.
Re[111]: Когда это наконец станет defined behavior?
От: σ  
Дата: 22.08.23 10:13
Оценка:
σ>>Я тоже вижу что не ошибся в своих подозрениях что ты не знаешь разницы между созданием объекта и началом времени жизни объекта.
σ>>Параграф про lifetime start описывает как начинается lifetime уже существующего (созданного) объекта, а не про то, как объект создаётся.

S>Замечательно, но пока вы оцениваете мои знания вы никаких доводов в пользу своей точки зрения не приводите.


Это не моя точка зрения. Это стандарт. Поищи по слову created, например.

σ>>>>>>Не понел, в (1) два объекта, что ли?


S>>>>>Нет. Просто точка (1) она не точка, это временной отрезок, который начинается, длится и заканчивается. Когда он начинается в программе появляется объект типа demo


σ>>>>Пруф можно?


S>>>Пруф на что? На здравый смысл?


σ>>Ну если ты хочешь переходить на такой детсадовский уровень, то ок: здравый смысл говорит что появляется объект типа const demo.


S>Появляется. Не вижу здесь противоречий с тем, что я сказал. В чем предмет спора?


Не прикидывайся. Появляется только объект типа const demo. Это не только здравому смыслу соответствует.

S>>>>>для которого вызывается конструктор, когда этот отрезок завершается этот самый объект становится доступным внутри f() под именем d. Но пока этот отрезок не завершился, внутри f() объекта d еще нет


σ>>>>В смысле, переменная d не связана ещё ни с каким объектом, или что?


S>>>В смысле что самого понятия d не существует пока инициализация d не завершена.


σ>>Что такое «самого понятия d не существует»? Ты можешь перестать выражаться всякими размытыми фразами? Что за «самоё понятие d»?


S>А вы попробуйте читать что вам пишут. У вас в коде есть строка:

S>
void f() {
 const demo d;
  ...
}

S>Так вот, пользоваться d вы сможете только когда завершится его создание (т.е. выделение места и инициализация). До этого момента у вас в f() никакого d еще нет. Вот когда создание d завершится успешно, тогда d в f у вас есть. А до того нет. Вообще.

Т.е. ты всё это время пытался выродить мысль, что внутри f lookup для имени d найдёт переменную d только в точке программы после const demo d?
А зачем ты это пытался сказать? Как это влияет на тип объекта?

σ>>И она тут к чему? В ней написано что-то про самоё понятие d?


S>В ней написано про момент, когда объект уже "типа есть" но лайфтайм для него начатым еще не считается.


И какого же типа этот объект?

S>А это как раз имеет прямое отношение к d, которого еще нет, пока его инициализация не завершилась


ЧТО ЗНАЧИТ ЧТО d ЕЩЁ НЕТ?
Как переменная, d "есть" ещё без всяких инициализаций и вообще без выполнения программы, "синтаксически": в теле f есть переменная d.

S>Вы хотите перейти на обсуждение персоналий? Или мы таки продолжим говорить про происходящее в C++?


Продолжим?!!
МЫ почти не начинали говорить о C++. В смысле, я-то с самого начала говорил, а ты десятки сообщений вываливал своё личное мнение/«эмпирический опыт» что, по-твоему, надо считать константным объектом и проч. подобное.
Re[112]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 22.08.23 10:29
Оценка:
Здравствуйте, σ, Вы писали:

σ>Это не моя точка зрения. Это стандарт. Поищи по слову created, например.


Это уже заход на какой-то N-ый круг.

σ>Не прикидывайся. Появляется только объект типа const demo. Это не только здравому смыслу соответствует.


Только вот фокус в том, что пока инициализация const demo d не завершилась, есть объект типа demo.

σ>Т.е. ты всё это время пытался выродить мысль, что внутри f lookup для имени d найдёт переменную d только в точке программы после const demo d?


Нет, про lookup имен я вообще ничего не говорил. Речь про то, когда объекты начинают жить и в каком виде.

σ>Как это влияет на тип объекта?


Тем, что внутри конструктора мы имеем demo. После его успешного завершения уже const demo.

S>>В ней написано про момент, когда объект уже "типа есть" но лайфтайм для него начатым еще не считается.


σ>И какого же типа этот объект?


Внутри конструктора -- demo.

S>>Вы хотите перейти на обсуждение персоналий? Или мы таки продолжим говорить про происходящее в C++?


σ>Продолжим?!!

σ>МЫ почти не начинали говорить о C++. В смысле, я-то с самого начала говорил, а ты десятки сообщений вываливал своё личное мнение/«эмпирический опыт» что, по-твоему, надо считать константным объектом и проч. подобное.

Ну как-то так получается, что эмпирический опыт исходя из которого я здесь привожу примеры, основан на C++. Следовательно я говорю про C++.
Re[104]: Когда это наконец станет defined behavior?
От: vdimas Россия  
Дата: 22.08.23 10:29
Оценка:
Здравствуйте, vopl, Вы писали:

V>>До С++17 некоторые компиляторы падают во время исполнения, некоторые выдают мусор. ))

V>Эта суть понятна в полной мере.

Вывод был
0, 1
1, 2


Хотя компилятор мог бы закешировать значения index в регистрах или вообще расположить экземпляры объектов в регистрах, ведь их размер это позволяет.
Т.е., программа могла выдать и
0, 1
1, 2

и
0, 0
0, 0

и просто упасть, если бы компилятор "не обратил внимание" на протекающий this.


V>По прежнему имею мнение что сабжевый "гипотетический UB" имеет такую же природу, но несколько другой механизм активации


Сабжевый ваш UB другой, имеет природу недоинициализированных глобальных переменных в динамической фазе инициализации.
Это очень старый UB, который живёт с самых первых версий С++, когда о RVO еще не слышали. ))

Этот ваш UB легко воспроизводим и без константности.
Re[105]: Когда это наконец станет defined behavior?
От: vopl Россия  
Дата: 22.08.23 10:29
Оценка:
Здравствуйте, vdimas, Вы писали:

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


V>>ну так там оно и есть все "одновременно".


V>Только в случае глобальных переменных и только в случае доступа к переменным в фазе динамической инициализации модуля, где эта инициализация еще не завершена.

V>Это ДРУГОЕ UB. ))

глобальность непричем, вот такой кейс имеет то же самое "гипотетическое UB"

struct T {int m;};

T make()
{
    T inner;
    inner.m = 220;
    return inner;
}

int main()
{
    const T outer = make();

    return 0;
}



V>>Константный объект, используемый сквозь неконстантное имя, подвергается модификации.


V>Для локальных констант оно невоспроизводимо, т.к. доступ к константе происходит только после инициализации переменной.

не важно когда происходит доступ. Тип объекта, определяемый декларацией потенциально является константным. На этой основе компилятор может делать всякие предположения относительно доступа к этому объекту. И объект после своего создания/инициализации используется как мутабельный.

вот так оно может быть развернуто компилятором

struct T {int m;};

int main()
{
    count T outer{};// только конструктор будет от неконстантного имени. Да я знаю что конструктору плевать, просто отмечаю сей факт

    T& inner = const_cast<T&>(outer);
    inner.m = 220;

    return 0;
}



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



V>>в случае NRVO объект внутри и снаружи — это один и тот же объект (σ приводил ссылку на стандарт)


V>Но внешняя ссылка недоступна программе, т.е. компилятору негде внести неопределённое поведение.



V>>следовательно его время жизни уже началось, он уже создан.


V>Наоборот, время жизни еще не началось.

V>(у меня такое ощущение, что часть слов вы просто не воспринимаете — слова проходят сквозь вас)

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

V>У данных, описанных в модуле, есть две фазы инициализации — статическая и динамическая.

V>В статической фазе происходит загрузка данных в сегмент данных из соотв.сегмента образа-бинарника.

V>В статической фазе инициализируются константы времени компиляции, например:

V>
V>const int i = 42;
V>

V>(туда же constexpr для вычислимых значений)

V>В динамической фазе происходит динамическая инициализация, например:

V>
V>const int i = calcValue();
V>

V>(если последняя несводима к constexpr)

V>Что характерно, в статической фазе константе const int i будет присвоено значение 0, а в динамической фазе эта константа будет перезаписана результатом вызова calValue(). Не смущает, ы? ))


это все не важно

V>То же самое касается конструкторов объектов, если эти конструкторы выполняются только динамически.


V>Так вот, услышьте уже, что доступ к неинициализированным данным модуля является UB и безо-всякого RVO/NRVO, т.е. это другое UB, нерелевантное обсуждаемому.


Услышал. Сабжевое "гипотетическое UB" — не про доступ к неинициализированным данным. В кейсе с "гипотетическим UB" все инициализировано до использования.

V>И тот якобы пример, который вы привели, он про UB вокруг динамической фазы инициализации. И об этом я сказал твоему союзнику с самого начала, бо вопрос не стоит и выеденного яйца, там всё слишком очевидно. ))


Нет. Это был пример в котором объявлен константный объект, он создан/инициализирован и потом с ним идет работа как не с константным, что есть UB.

V>Но после динамической фазы инициализации модуля, либо же, в этой фазе, но с учётом гарантированной последовательности инициализации глобальных переменных модуля, можно избежать упомянутого мною UB, и RVO/NRVO опять на него никак не влияют. Всё.


Не в ту сторону все.

V>Тут надо рассуждать не об RVO/NRVO, а об prvalue, которое, начиная с C++17 может не быть материализовано до момента необходимости.

V>См пример рядом:
V>http://www.rsdn.org/forum/cpp/8585549.1

V>Необязательность материализации prvalue — более общее допущение, которое способно даже удалять локальные промежуточные переменные, протягивая "сквозь них" prvalue в процессе оптимизации бинарника. Но! мы можем рассуждать исключительно и только о семантике, описанной в коде, как будто нет никаких допущений относительно необязательности материализации prvalue, нет никаких RVO/NRVO и прочих трюков. Именно поэтому для prvalue всё еще требуются конструкторы копирования, которых в конечном образе может и не быть за ненадобностью — они нужны исключительно для описания исходной семантики кода, которая гарантируется компилятором, с учётом замечания про побочные эффекты.


V>По ссылке приведён как раз побочный эффект конструктора, где this протекает "куда-то еще", в какой-то другой контекст, необнаруживаемый компилятором при компиляции текущего модуля.

V>(registrar по ссылке мог быть объявлен в другом модуле)

Пример посмотрел, понял, там отписал. В нем другой способ инициирования записи в константный объект, в общем, этот пример не принимается как полный, но очень хорошо показывает запись в константный объект, которая есть и в кейсе с "гипотетическим UB"
Re[105]: Когда это наконец станет defined behavior?
От: vopl Россия  
Дата: 22.08.23 10:35
Оценка:
Здравствуйте, vdimas, Вы писали:

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


V>>>До С++17 некоторые компиляторы падают во время исполнения, некоторые выдают мусор. ))

V>>Эта суть понятна в полной мере.

V>Вывод был

V>
V>0, 1
V>1, 2
V>


V>Хотя компилятор мог бы закешировать значения index в регистрах или вообще расположить экземпляры объектов в регистрах, ведь их размер это позволяет.

V>Т.е., программа могла выдать и
V>
V>0, 1
V>1, 2
V>

V>и
V>
V>0, 0
V>0, 0
V>

V>и просто упасть, если бы компилятор "не обратил внимание" на протекающий this.


V>>По прежнему имею мнение что сабжевый "гипотетический UB" имеет такую же природу, но несколько другой механизм активации


V>Сабжевый ваш UB другой, имеет природу недоинициализированных глобальных переменных в динамической фазе инициализации.

V>Это очень старый UB, который живёт с самых первых версий С++, когда о RVO еще не слышали. ))

V>Этот ваш UB легко воспроизводим и без константности.


Да штош такое то) Сабжевый наш UB — НЕ имеет природу недоинициализированных глобальных переменных в динамической фазе инициализации. Он про другое. Не про погрешности в инициализации. Он про запист в гипотетически константный, нормально проинициализированный объект.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.