Информация об изменениях

Сообщение Re[100]: Когда это наконец станет defined behavior? от 22.08.2023 7:48

Изменено 22.08.2023 8:01 vdimas

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 (это не важно) НО теперь совершенно другого объекта (он имеет уже ссылочноый тип и связывается с тем первичным объектом, но это тоже не важно)

Э, нет — это архиважно!

Я могу написать так:
const std::map<int, int> & immutableMap = buildMap();

Но не могу так:
std::map<int, int> & immutableMap = buildMap();


Потому что захватить для владения временный объект я могу только по константной ссылке, т.е. после захвата этого значения оно превращается в константное — к типу знаения добавляется соотв. модификатор. И теперь без хака-реинтерпретации памяти ты эту константность никак не нарушишь.

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


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).
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 (это не важно) НО теперь совершенно другого объекта (он имеет уже ссылочноый тип и связывается с тем первичным объектом, но это тоже не важно)

Э, нет — это архиважно!

Я могу написать так:
const std::map<int, int> & immutableMap = buildMap();

Но не могу так:
std::map<int, int> & immutableMap = buildMap();

Потому что захватить для владения временный объект я могу только по константной ссылке, т.е. после захвата этого значения оно превращается в константное — к типу знаения добавляется соотв. модификатор. И теперь без хака-реинтерпретации памяти ты эту константность никак не нарушишь.

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


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).