Здравствуйте, samius, Вы писали:
V>>Ну коль синтаксис другой, то и спецификации дополнительные нужны понятно. V>>Это не ответ. Давай еще раз, чем ссылка отличается от любой другой константной переменной? S>Ок, насыплю побольше S>* указатель может ссылаться на NULL
К моему большому сожалению, ссылка тоже может. Еще как.
S>* невозможно взять адрес ссылки (уже было, но для полноты списка) S>* невозможно объявить ссылку на ссылку как указатель на указатель
Это повтор предыдущего (насчет адреса), т.к. иначе таки можно было бы взять адрес ссылки путем взятия ссылки на ссылку и разыменование адреса.
S>* у ссылок нет арифметики (в отличии от константного указателя)
Есть, ведь адрес объекта, на который ссылается аналогичный константный указатель, и лишь об адресной арифметике которого мы можем рассуждать, доступен через операцию & над ссылкой.
S>* переменная имеет адрес и размер, а ссылка лишь ссылается на место в памяти, предоставленное некой переменной
Ссылка имеет размер, конструктор и даже можно организовать ей оператор копирования, дабы пользовать в типах, которые можно хранить в стандартных контейнерах:
int nullTag;
int someValue = 42;
struct A {
int & reference;
A(int & r) : reference(r) {}
A() : reference(nullTag) {}
A & operator=(const A & aa) { new(this)A(aa.reference); return *this; }
bool isNull() const { return &reference == &nullTag; }
};
int main() {
A a;
std::cout << a.isNull() << std::endl;
a = A(someValue);
std::cout << a.isNull() << std::endl;
std::cout << sizeof(A[100]) << std::endl;
std::cout << sizeof(int&) << std::endl;
}
Посмотри на последнюю строку.
S>* в отличии от указателя, ссылка продлевает время жизни временного объекта
Не продлевает ни разу, ссылки на временный объект нельзя хранить.
Наверно ты имел ввиду, что для случая константной ссылки возможно конструирование объекта "по-месту"? Дык, это работает банальный вызов конструктора во время приведения типов. И да, сохранять эту ссылку ни в коем случае нельзя, можно только пользовать в том scope, где этот временный объект, созданный для целей приведения типов, будет жив. Наиболее употребимо как аргумент ф-ий.
V>>Адрес нельзя брать по спецификации, иначе бы невозможно было бы использование operator. взамен operator->. S>Неудовлетворительное объяснение.
Эээ... а попробуй поиграй с синтаксисом "от обратного", оч быстро объяснение перейдет в разряд вполне удовлетворительных.
S>В отличии от указателя (для которого определен оператор ->), ссылка представляет собой псевдоним объекта. Потому, что бы не применялось к ссылке, оно на самом деле применяется к значению, которое лежит в месте памяти, на которое ссылается ссылка.
Если адрес взять нельзя, то стадию разыменования адреса мы пропускаем в любом случае. Иначе просто ничего не сойдется.
V>>Константы надо обязательно инициализировать при объявлении, итого остается только отличие в operator->. S>Константный указатель можно проинициализировать NULL-ом.
Гы:
int * pi = NULL;
int & ri = *pi;
Дарю!
В общем, в сухом остатке имеем отсутствие operator-> и невозможность взять адрес для обеспечения этого.
V>>И да, я могу привести пример, где даже ссылки на статические члены всё равно будут переменными (т.е. занимать память): V>>extern int & i; // заметь, без инициализации S>Еще бы... Но это не объявление ссылки. Это объявление того, что ссылка объявлена в другом месте.
Не... я возражал про память. Без link-time codogeneration память будет выделена, как ни крути.
V>>А если ссылка импортируется из DLL, то еще и с доп. переходником, т.е. +1 уровню косвенности. Итого, под эту ссылку будет выделено целых два слота памяти, длиной в машинное слово, вместо ни одной. S>А это не важно, т.к. взять адреса этих слотов не представляется возможным на уровне языка.
Дык и адреса одной ссылки не возможно. Я новый спек С++ еще не изучал подробно, но ИМХО вводить в стандарт то, что и так выводится из других частей непротиворечивым способом — это же избыточность. Или банальная невнимательность.
V>>Так же как могу привести пример, где ссылка на нестатические члены никогда не будет занимать лишней памяти: V>>
V>>void main() {
V>> int i = 0;
V>> int ref_i = i;
V>> std::cout << ref_i << std::endl;
V>>}
V>>
S>А где ссылка? V>>ref_i будет вычислена в compile-time, как и любое вычислимое в compile-time выражение, напр:
Упс, хотел написать int & ref_i = i;
S>Усмотрение компилятора в отношении ООП меня совершенно не волнуют. Я вообще могу (теоретически) допустить, что компилятор может произвести graph rewriting с редукцией и не оставить ничего, что бы напоминало об исходном коде. Ни узнаваемых структур данных, ни переменных... Это не заставит меня считать что в исходном коде на C++ не стало структур данных и переменных.
Я конкретно про гарантированные compile-time вычисления говорил, не уводи в сторону. Фишка в том, что гарантрованные compile-time вычисления происходят даже в отсутствии оптимизаций. И вычисление констант из той же области видимости — аналогично. Поэтому и привел пример с ref_i (с опиской), что там константа вычислима в compile-time.
S>>>Более того, устоявшимся и наиболее употребимым является выражение "ссылка на переменную", а не "ссылочная переменная". V>>Не слышал такого, бо ссылка может быть и на объект в куче. S>может. Ссылка она вообще на место.
Ну и как тут прикрутить выражение "ссылка на переменную"? Я пользуюсь лишь мемом "ссылка на значение". А связано ли это значение с переменной или нет — дело десятое, напр. адрес значения может быть вычислимым.
S>Важное отличие в том, что объявление переменной приводит к созданию storage location для переменной, а объявление ссылки — нет. При этом неважно, выкинет компилятор это storage location, как в случае с ref_i, или нет.
Ну? Точно так же как объявление T * const ptr прямо по стандарту не обязательно приводит к выделению памяти под переменную, если выражение вычислимо в compile-time. Потому что константа. А если не вычислимо в рантайм, то в обоих случаях память под переменную еще как выделяется. Потому что переменная константного типа. Это такой хитрый ньюанс С++, который следовало бы иметь ввиду, из-за которого оч разное поведение у статических констант и экземплярных, например. Я именно это тебе и толкую, что для аналогичных случаев оба варианта ведут себя полностью аналогично.
V>>Там в переменной целиком хранится состояние объекта, так что не передергивайте.
L>Вы путаете понятия разных уровней.
L>Переменная — понятие конкретного языка программирования, оно служит для идентификации какого-то значения, используемого в прграмме. L>Поэтому в каком-то смысле переменная является "ссылкой".
L>
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, Lloyd, Вы писали:
V>>>Термин переменная в ЯП имеет определение. L>>С удовольствием выслушаю ваше определение.
V>Да не мое, чего уж там... V>Меня тогда еще в проекте не было, когда это определение уже было, в Вики дается без изменений оригинала.
Согласно этому определению ссылка не является переменной, т.к. переменной называется область памяти, в которой находится значение. Ссылка лишь ссылается на эту область памяти и только.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
S>>* указатель может ссылаться на NULL
V>К моему большому сожалению, ссылка тоже может. Еще как.
Да, но в теории не должна.
S>>* невозможно взять адрес ссылки (уже было, но для полноты списка) S>>* невозможно объявить ссылку на ссылку как указатель на указатель
V>Это повтор предыдущего (насчет адреса), т.к. иначе таки можно было бы взять адрес ссылки путем взятия ссылки на ссылку и разыменование адреса.
S>>* у ссылок нет арифметики (в отличии от константного указателя)
V>Есть, ведь адрес объекта, на который ссылается аналогичный константный указатель, и лишь об адресной арифметике которого мы можем рассуждать, доступен через операцию & над ссылкой.
Так это адресная арифметика над адресом, который доступен через операцию &, а не над ссылкой.
S>>* переменная имеет адрес и размер, а ссылка лишь ссылается на место в памяти, предоставленное некой переменной
V>Ссылка имеет размер, конструктор и даже можно организовать ей оператор копирования, дабы пользовать в типах, которые можно хранить в стандартных контейнерах: V>
V>Посмотри на последнюю строку.
Если даже ссылка имеет собственный адрес и размер, то значение, на которое ссылается ссылка, хранится не по этому адресу. И этим ссылка отлиается от переменной, на которую она ссылается.
S>>* в отличии от указателя, ссылка продлевает время жизни временного объекта
V>Не продлевает ни разу, ссылки на временный объект нельзя хранить.
объявление ссылки на временный объект продлевает жизнь временного объекта до выхода из скопа, в котором определена ссылка. Это не я придумал. Если какой-то компилятор это не выполняет, моя хата с краю.
V>Наверно ты имел ввиду, что для случая константной ссылки возможно конструирование объекта "по-месту"? Дык, это работает банальный вызов конструктора во время приведения типов. И да, сохранять эту ссылку ни в коем случае нельзя, можно только пользовать в том scope, где этот временный объект, созданный для целей приведения типов, будет жив. Наиболее употребимо как аргумент ф-ий.
Я о временных объектах, которые создает компилятор на стеке при вычислении выражений, включая приведения типов, вызов функций и т.п. При отсутствии ссылки на такой объект, компилятор волен удалить его сразу после того, как тот перестал быть нужен. А ссылка продляет время жизни такого объекта до выхода из скопа.
V>>>Адрес нельзя брать по спецификации, иначе бы невозможно было бы использование operator. взамен operator->. S>>Неудовлетворительное объяснение.
V>Эээ... а попробуй поиграй с синтаксисом "от обратного", оч быстро объяснение перейдет в разряд вполне удовлетворительных.
меня мое объяснение больше устраивает.
S>>В отличии от указателя (для которого определен оператор ->), ссылка представляет собой псевдоним объекта. Потому, что бы не применялось к ссылке, оно на самом деле применяется к значению, которое лежит в месте памяти, на которое ссылается ссылка.
V>Если адрес взять нельзя, то стадию разыменования адреса мы пропускаем в любом случае. Иначе просто ничего не сойдется.
А мы ее итак пропускаем, ведь ссылка — псевдоним объекта, а не указателя на него.
S>>Константный указатель можно проинициализировать NULL-ом.
V>Гы: V>
V>int * pi = NULL;
V>int & ri = *pi;
V>
V>Дарю!
Да не стоит оно того. Здесь ссылка, кстати, проинициализирована не NULL-ом, а тем int-ом, который получается при разыменовании NULL-а.
V>В общем, в сухом остатке имеем отсутствие operator-> и невозможность взять адрес для обеспечения этого.
Ну и область памяти, которая не имеет отношение к значению, если вообще существует.
V>>>extern int & i; // заметь, без инициализации S>>Еще бы... Но это не объявление ссылки. Это объявление того, что ссылка объявлена в другом месте.
V>Не... я возражал про память. Без link-time codogeneration память будет выделена, как ни крути.
V>>>А если ссылка импортируется из DLL, то еще и с доп. переходником, т.е. +1 уровню косвенности. Итого, под эту ссылку будет выделено целых два слота памяти, длиной в машинное слово, вместо ни одной. S>>А это не важно, т.к. взять адреса этих слотов не представляется возможным на уровне языка.
V>Дык и адреса одной ссылки не возможно. Я новый спек С++ еще не изучал подробно, но ИМХО вводить в стандарт то, что и так выводится из других частей непротиворечивым способом — это же избыточность. Или банальная невнимательность.
А это о чем?
V>>>Так же как могу привести пример, где ссылка на нестатические члены никогда не будет занимать лишней памяти: V>>>ref_i будет вычислена в compile-time, как и любое вычислимое в compile-time выражение, напр:
V>Упс, хотел написать int & ref_i = i;
Занимает или не занимает память ссылка — неважно. Важно то, что значение лежит не в той памяти, которую занимает или не занимает ссылка. Значение лежит в памяти переменной (если у той она есть).
S>>Усмотрение компилятора в отношении ООП меня совершенно не волнуют. Я вообще могу (теоретически) допустить, что компилятор может произвести graph rewriting с редукцией и не оставить ничего, что бы напоминало об исходном коде. Ни узнаваемых структур данных, ни переменных... Это не заставит меня считать что в исходном коде на C++ не стало структур данных и переменных.
V>Я конкретно про гарантированные compile-time вычисления говорил, не уводи в сторону. Фишка в том, что гарантрованные compile-time вычисления происходят даже в отсутствии оптимизаций. И вычисление констант из той же области видимости — аналогично. Поэтому и привел пример с ref_i (с опиской), что там константа вычислима в compile-time.
А я говорил о том что результат компиляции может быть несопоставим с терминами языка, потому решать, что есть переменная (в языке) а что нет, на основании бинарного кода не годится.
S>>может. Ссылка она вообще на место.
V>Ну и как тут прикрутить выражение "ссылка на переменную"? Я пользуюсь лишь мемом "ссылка на значение". А связано ли это значение с переменной или нет — дело десятое, напр. адрес значения может быть вычислимым.
Ссылка на переменную оозначает ссылку на значение, хранящееся в переменной.
S>>Важное отличие в том, что объявление переменной приводит к созданию storage location для переменной, а объявление ссылки — нет. При этом неважно, выкинет компилятор это storage location, как в случае с ref_i, или нет.
V>Ну? Точно так же как объявление T * const ptr прямо по стандарту не обязательно приводит к выделению памяти под переменную, если выражение вычислимо в compile-time. Потому что константа. А если не вычислимо в рантайм, то в обоих случаях память под переменную еще как выделяется. Потому что переменная константного типа. Это такой хитрый ньюанс С++, который следовало бы иметь ввиду, из-за которого оч разное поведение у статических констант и экземплярных, например. Я именно это тебе и толкую, что для аналогичных случаев оба варианта ведут себя полностью аналогично.
А я толкую что мы не определяем будет ли то что написано в исходниках функцией по тому заинлайнит компилятор тело или нет. Так же мы не будем определять что является переменной по результату компиляции.
Здравствуйте, vdimas, Вы писали:
L>>С удовольствием выслушаю ваше определение.
V>Да не мое, чего уж там... V>Меня тогда еще в проекте не было, когда это определение уже было, в Вики дается без изменений оригинала.
Если не затруднит, не могли бы вы уточнить, что именно в определении противоречит сказанному мной (Имя никогда не означает "само себя".)?
Здравствуйте, vdimas, Вы писали:
L>>Переменная — понятие конкретного языка программирования, оно служит для идентификации какого-то значения, используемого в прграмме. L>>Поэтому в каком-то смысле переменная является "ссылкой".
L>>
V>Эээ... че-то я теряюсь, на всяк случай тут приводил разбор способов адресации: http://www.rsdn.ru/forum/philosophy/4505309.1.aspx
Здравствуйте, samius, Вы писали:
V>>Меня тогда еще в проекте не было, когда это определение уже было, в Вики дается без изменений оригинала.
S>Согласно этому определению ссылка не является переменной, т.к. переменной называется область памяти, в которой находится значение. Ссылка лишь ссылается на эту область памяти и только.
Я тебе уже показывал, что ссылка занимает вполне конкретную память, могу опять:
struct A {};
struct B { A & a; };
std::cout
<< sizeof(A) << std::endl
<< sizeof(B) << std::endl
<< sizeof(B&) << std::endl;
Но это ссылочный тип, поэтому в сравнении с обычной переменной мы имеем лишние уровни косвенности (тут +1), т.е. сначала идет обращение к переменной-ссылке, извлечение адреса целевого объекта из нее, а затем обращение к целевому объекту по этому адресу. Аналогично использованию переменной ссылочного типа в дотнете.
Здравствуйте, Lloyd, Вы писали:
L>Если не затруднит, не могли бы вы уточнить, что именно в определении противоречит сказанному мной (Имя никогда не означает "само себя".)?
Мне был странен сам наблюдаемый спор вокруг того, что же означает имя переменной, поэтому отослал к определению.
Здравствуйте, Sinclair, Вы писали:
S>Вот, например, "статическая переменная", как известно из букваря, используется в дотнете при помощи инструкции ldsfld/ldsflda. Откуда в MSIL возьмётся абсолютный адрес — непонятно.
MSIL не есть машинный язык. Он слишком высокоуровневый. При любой машинной реализации у статической ячейки будет известный (неизменный, фиксированный) времени выполнения адрес, будь то адрес числовой, как мы привыкли, или даже некий символьный/токен в какой-нить гипотетической ассоциативной машине. С динамическими ячейками это не так, их текущий адрес где-то хранится, а именно в переменных ссылочного типа.
S>Вообще, понятие "адрес" в спецификации дотнета применимо исключительно к unmanaged pointer types, см. секцию 8.9.2.
Правильно, и чтобы получить адрес объекта, его надо запинить, т.к. GC двигает эти объекты. Но из этого следует лишь следующее:
— GC двигает объекты
— чтобы узнать текущий и достоверный адрес объекта, сам объект надо зафиксировать в памяти
— оперирование ссылочными типами прозрачно для программиста
И не более.
И да, unmanaged pointer types все еще обслуживаются опкодами MSIL, такими же, как и managed, если что-то забыл...
S>Понятие "абсолютное смещение" — это, надо полагать, результат вычитания двух поинтеров. Применимо только к unmanaged pointers, unverifiable. То есть, в легальной дотнет-программе понятие смещения использовать нельзя.
Можно, для явного размещения полей, для маршаллинга даже без явного размещения полей. Узнать можно смещение любого поля уже загруженного типа. В любой легальной дотнет-программе.
S>Понятие "адреса объекта" в спецификации дотнета не используется. Понятие "адрес текущего фрейма стека" — тоже.
Ты имел ввиду в шарпе не используется? А в каком высокоуровневом ЯП напрямую фрейм стека доступен? И почему относительно других языков никто не возражает, что доступ к локальным переменным относительный, относительно текущего фрейма стека? Понятие фрейма стека в ходит в описание работы дотнетной байт-машины, так что для нее всё это справедливо. Ну и к тому же в MSIL используется и то и другое, если речь именно о дотнете, а не о шарпе. Чем тебе индекс стековой переменной не адрес?
Здравствуйте, vdimas, Вы писали:
V>MSIL не есть машинный язык. Он слишком высокоуровневый. При любой машинной реализации у статической ячейки будет известный (неизменный, фиксированный) времени выполнения адрес, будь то адрес числовой, как мы привыкли, или даже некий символьный/токен в какой-нить гипотетической ассоциативной машине. С динамическими ячейками это не так, их текущий адрес где-то хранится, а именно в переменных ссылочного типа.
Тем не менее, обсуждать семантику MSIL в терминах некоторой конкретной машинной реализации мне кажется несколько поспешным. И MSIL никак не слишком высокоуровневый. Его уровень — в самый раз. Вся семантика дотнета определена в терминах MSIL. Семантика шарпа определена в ещё более высокоуровневой форме. Там то, что выглядит стековой переменной, запросто может в MSIL превратиться в поле объекта.
V>Можно, для явного размещения полей, для маршаллинга даже без явного размещения полей. Узнать можно смещение любого поля уже загруженного типа. В любой легальной дотнет-программе.
И тем не менее, смещение любого поля в обращении к полю не используется. Если не верите — откройте рефлектором любую дотнет-программу и посмотрите, как устроена команда ldfld.
S>>Понятие "адреса объекта" в спецификации дотнета не используется. Понятие "адрес текущего фрейма стека" — тоже.
V>Ты имел ввиду в шарпе не используется? А в каком высокоуровневом ЯП напрямую фрейм стека доступен? И почему относительно других языков никто не возражает, что доступ к локальным переменным относительный, относительно текущего фрейма стека?
Относительно каких языков? Относительно ассемблера — не возражает.
Относительно даже С уже вопрос о фрейме стека является чисто умозрительным. Никто не мешает оптимизатору разместить локальные переменные, скажем, в регистрах. Именно потому, что доступ к локальным переменным формулируется по именам локальных переменных, безо всяких ссылок на фрейм стека. V>Понятие фрейма стека в ходит в описание работы дотнетной байт-машины, так что для нее всё это справедливо.
Рекомендую (в рамках само-ликбеза) всё же ознакомиться с описанием работы дотнетной байт-машины. Потому что managed stack устроен совершенно не так, как вы пытаетесь это представить, и адреса его ячеек нигде в описании не фигурируют.
V>Ну и к тому же в MSIL используется и то и другое, если речь именно о дотнете, а не о шарпе. Чем тебе индекс стековой переменной не адрес?
Тем, что это никакой не адрес.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
V>>Любая адресация, кроме непосредственной, является "ссылочной", но они всё еще такие разные.
L>Ничего личного, но вы путаете понятия времени исполнения и понятия языка программирования.
Если бы способы адресации были не важны, их бы не проходили на первых курсах профильной специальности. Надо понимать что и как работает, чтобы адекватно использовать любую технологию, не делая заведомо неверных допущений (суть проявляя безалаберность и безответственность). Таки запас по эффективности и ресурсам пока еще не тысячекратный, чтобы позволить себе это.
Здравствуйте, Sinclair, Вы писали:
S>Тем не менее, обсуждать семантику MSIL в терминах некоторой конкретной машинной реализации мне кажется несколько поспешным. И MSIL никак не слишком высокоуровневый. Его уровень — в самый раз. Вся семантика дотнета определена в терминах MSIL. Семантика шарпа определена в ещё более высокоуровневой форме. Там то, что выглядит стековой переменной, запросто может в MSIL превратиться в поле
объекта.
Замыкания меняют семантику переменных, время ее жизни перестает быть ограниченной scope, в котором она определена, поэтому не вижу противоречий. Таки время жизни переменной все еще очень важное понятие, даже в шарпе.
V>>Можно, для явного размещения полей, для маршаллинга даже без явного размещения полей. Узнать можно смещение любого поля уже загруженного типа. В любой легальной дотнет-программе. S>И тем не менее, смещение любого поля в обращении к полю не используется. Если не верите — откройте рефлектором любую дотнет-программу и посмотрите, как устроена команда ldfld.
Обращение по токену относитльно экземпляра. Большая разница? что должен озанчать токен, чтобы всё это работало правильно У ЛЮБОГО экземпляра этого типа? И чем тебе токен не адрес, в случае даже ассоциативной адресации, как в объектах языка JS, например?
V>>Ты имел ввиду в шарпе не используется? А в каком высокоуровневом ЯП напрямую фрейм стека доступен? И почему относительно других языков никто не возражает, что доступ к локальным переменным относительный, относительно текущего фрейма стека? S>Относительно каких языков? Относительно ассемблера — не возражает.
Мне понятие "локальных переменных" преподавали когда-то на примере Паскаля. Не вижу принципиальных отличий от шарпа. Без сущности "стек", "стековые переменные", "фреймы стека" невозможно описать семантику дотнетной байт-машины.
S>Относительно даже С уже вопрос о фрейме стека является чисто умозрительным. Никто не мешает оптимизатору разместить локальные переменные, скажем, в регистрах. Именно потому, что доступ к локальным переменным формулируется по именам локальных переменных, безо всяких ссылок на фрейм стека.
Ну мало ли что есть в современных оптимизаторах. Мы же оперируем семантикой, т.е. программа должна работать даже на таких процессорах, например, все регистры которого индексные, и предполагают исключительно косвенную адресацию, хоть в терминах программы мы исопльзуем непосредственную или прямую. Семантика меняться не должна. Для этого должна быть некая эталонная модель, к которой мы привяжем семантику программы, закрыв гляза на подробности реализации модели на разных платформах. Относительно байт-машины дотнета сюда можно вставлять предыдущий абзац.
V>>Понятие фрейма стека в ходит в описание работы дотнетной байт-машины, так что для нее всё это справедливо. S>Рекомендую (в рамках само-ликбеза) всё же ознакомиться с описанием работы дотнетной байт-машины. Потому что managed stack устроен совершенно не так, как вы пытаетесь это представить, и адреса его ячеек нигде в описании не фигурируют.
V>>Ну и к тому же в MSIL используется и то и другое, если речь именно о дотнете, а не о шарпе. Чем тебе индекс стековой переменной не адрес? S>Тем, что это никакой не адрес.
По определению самого термина "адреса", адрес — это порядковый номер ячейки. Так что, мое вам с кисточкой в плане само-ликбеза.
Здравствуйте, vdimas, Вы писали:
L>>Ничего личного, но вы путаете понятия времени исполнения и понятия языка программирования.
V>Если бы способы адресации были не важны, их бы не проходили на первых курсах профильной специальности. Надо понимать что и как работает, чтобы адекватно использовать любую технологию, не делая заведомо неверных допущений (суть проявляя безалаберность и безответственность). Таки запас по эффективности и ресурсам пока еще не тысячекратный, чтобы позволить себе это.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
S>>Согласно этому определению ссылка не является переменной, т.к. переменной называется область памяти, в которой находится значение. Ссылка лишь ссылается на эту область памяти и только.
V>Я тебе уже показывал, что ссылка занимает вполне конкретную память, могу опять:
А я могу показать что память, которую занимает ссылка, не размещает в себе значение, на которое она ссылается.
V>Но это ссылочный тип, поэтому в сравнении с обычной переменной мы имеем лишние уровни косвенности (тут +1), т.е. сначала идет обращение к переменной-ссылке, извлечение адреса целевого объекта из нее, а затем обращение к целевому объекту по этому адресу.
Ну так лишний уровень косвенности и отличает ссылку от переменной, а не сближает их.
V>Аналогично использованию переменной ссылочного типа в дотнете.
ссылочный тип в дотнете семантически ближе к указателю C++, чем к ссылке.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, Sinclair, Вы писали:
S>>Вот, например, "статическая переменная", как известно из букваря, используется в дотнете при помощи инструкции ldsfld/ldsflda. Откуда в MSIL возьмётся абсолютный адрес — непонятно.
V>MSIL не есть машинный язык. Он слишком высокоуровневый.
И C++ не есть машинный язк.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, DarkGray, Вы писали:
DG>>теперь обоснуй почему на основе такого определения времени нельзя использовать вот такую функцию для identity: DG>>идентичность объектов определяется как идентичность состояния объектов в моменты времени t, когда g(t) > 0. S>Потому что на основе такого определения нам не удастся определить, какому объекту мы отдаём сообщения.
если нужна формальная сторона: можно доопределить (есть и другие варианты доопределения взависимости от требований задачи) такое поведение как: если объект не получилось идентифицировать с заданной точностью посылка сообщения заканчивается получением ошибки, если сообщение с ответом, и игнорируется, если сообщение без ответа.
зы
напомню, что ООП не требует, чтобы все сообщения обязаны доходить до адресата без потерь.
DG>>в моделях: последовательность событий, которые как будто время, и время — это совсем разные вещи. S>Да ладно? Ну расскажите мне, что же такое время в моделях. S>Я просто компьютерным наукам не обучен, кроме университетского курса математики и физики ничего не знаю.
время — с точки зрения моделирования, это изменения (нет изменений, нет и времени).
раз есть изменение:
то появляется атомарный квант состояния(пространства), которое может измениться
появляется атомарный квант времени, через которое может что-то поменяться.
раз есть несколько(две) плоскостей: состояние(пространство) * время, то они могут быть однородными относительно друг друга, а могут быть и не однородными. при неоднородностях относительно друг друга становится значимым насколько одна плоскость неоднородна относительно себя же в одних и тех же координатах другой плоскости.
изменение требует определение двух функций идентичности: одна специфицирует — как определяется, что объект один и тот же при разных квантах времени, другая специфирует — как определяется, что в объектах произошли изменения.
и это не считая той функции идентичности на которую вы ссылаетесь, которая специфирует лишь как объекты различаются в "пространстве".
из-за того, что время глобально — оно влияет не только на элементы внутри модели, но и на саму модель — формируя ее изменение.
соотственно, для полноты должно быть задано что происходит, если начинает меняться сама модель (например, функции идентичности).
зы
вообще, вы с samius-ом рассматриваете самый просто вариант ООП (и что мне больше всего не нравится, что вы выдаете ее за догму, даже не понимая, какие ограничения вы при этом в нее заложили, который нет в самой концепции ООП)
вы рассматриваете ООП лишь для случая: строго однородное строго атомарное строго непрерывное пространство, условное время (в виде лишь условной последовательности сообщений), есть строго полное знание ("мир" знает всё про всех), все состояния строго однозначные (нет неопределенных состояний)
и соответственно, всех этих ограничений нет в самой модели ООП, а вы их накладываете сами.
отчасти это подтверждается тем, что до сих пор вами так и не приведены полные логичные доказательства, которые бы подтверждали вашу позицию.
ззы
на закуску пример, который показывает как всё непросто хотя бы с той же последовательностью сообщений.
например, часто считается, что события происходят строго одно за другим, но в ЯП — где сообщения(которые в ООП формально асинхронные) положены на вызовы функций (которые формально синхронные) — это не так. там часто ответ может приходить раньше, чем сообщение отправлено.
class Server
{
public void Ping(Action pong)
{
pong();
}
}
class Client
{
static public void Pong()
{
}
static void Main()
{
var server = new Server();
server.Ping(Pong);
}
}
в данном коде, с точки зрения клиента ответ приходит раньше, чем сообщение отправлено.
и при этом от данного поведения не помогают ни локи, ни apartment-модель, что на практике часто забывается, и приводит к трудноуловимым ошибкам.
это я к тому, что даже все ООП-языки, которые существуют, работают в рамках намного более полной ООП-модели, чем та, на которую вы ссылаетесь.
в данном коде, чтобы понять в чем проблема — требуется уже вводит такое понятие как неатомарность операции отправки сообщения.
Здравствуйте, vdimas, Вы писали:
V>Замыкания меняют семантику переменных, время ее жизни перестает быть ограниченной scope, в котором она определена, поэтому не вижу противоречий. Таки время жизни переменной все еще очень важное понятие, даже в шарпе.
Это правда. Но
V>Обращение по токену относитльно экземпляра. Большая разница? что должен озанчать токен, чтобы всё это работало правильно У ЛЮБОГО экземпляра этого типа? И чем тебе токен не адрес, в случае даже ассоциативной адресации, как в объектах языка JS, например?
Разница — принципиальна. Понятие адрес в программировании подразумевает определённую арифметику. В частности, возможность оперировать смещениями, что вы и пытаетесь делаеть, когда выдаёте за ликбез свои заблуждения.
V>Мне понятие "локальных переменных" преподавали когда-то на примере Паскаля. Не вижу принципиальных отличий от шарпа. Без сущности "стек", "стековые переменные", "фреймы стека" невозможно описать семантику дотнетной байт-машины.
Вы всё же почитайте это описание. Те стеки, которые фигурируют в описании семантики дотнетной байт-машины, это совсем не тот стек, которым вы управляете на ассемблере. А то, как вам преподавали понятие "локальных переменных", пусть остаётся на совести вашего преподавателя.
V>Ну мало ли что есть в современных оптимизаторах. Мы же оперируем семантикой, т.е. программа должна работать даже на таких процессорах, например, все регистры которого индексные, и предполагают исключительно косвенную адресацию, хоть в терминах программы мы исопльзуем непосредственную или прямую.
Совершенно верно. Поэтому семантика, которой мы оперируем, не имеет права опираться на потенциально устраняемые вещи типа "смещение относительно фрейма стека".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, DarkGray, Вы писали:
DG>зы DG>напомню, что ООП не требует, чтобы все сообщения обязаны доходить до адресата без потерь.
Я напомню свой вопрос про машину Тьюринга, оборудованную ненулевым количеством ошибок. Подумайте на досуге, зачем вам нужно такое ООП, в котором сообщения не обязаны доходить до адресата, и будет ли в нём хоть что-то, что не моделируется "обычным" ООП.
DG>>>в моделях: последовательность событий, которые как будто время, и время — это совсем разные вещи. S>>Да ладно? Ну расскажите мне, что же такое время в моделях. S>>Я просто компьютерным наукам не обучен, кроме университетского курса математики и физики ничего не знаю.
DG>время — с точки зрения моделирования, это изменения (нет изменений, нет и времени). DG>раз есть изменение: DG> то появляется атомарный квант состояния(пространства), которое может измениться DG> появляется атомарный квант времени, через которое может что-то поменяться.
DG>раз есть несколько(две) плоскостей: состояние(пространство) * время, то они могут быть однородными относительно друг друга, а могут быть и не однородными. при неоднородностях относительно друг друга становится значимым насколько одна плоскость неоднородна относительно себя же в одних и тех же координатах другой плоскости. DG>изменение требует определение двух функций идентичности: одна специфицирует — как определяется, что объект один и тот же при разных квантах времени, другая специфирует — как определяется, что в объектах произошли изменения.
DG>и это не считая той функции идентичности на которую вы ссылаетесь, которая специфирует лишь как объекты различаются в "пространстве".
DG>из-за того, что время глобально — оно влияет не только на элементы внутри модели, но и на саму модель — формируя ее изменение. DG>соотственно, для полноты должно быть задано что происходит, если начинает меняться сама модель (например, функции идентичности).
Прикольный поток сознания.
1. Вообще, время у нас появляется сразу же, как только появляются понятия "раньше" и "позже". Изменения — это уже следующий уровень.
2. Вы по-прежнему путаете отношение идентичности с отношением эквивалентности.
3. Время совершенно не обязано быть глобальным. "Синхронизация" времени в ООП-модели выполняется только в момент обмена сообщениями. Если два объекта получают сообщения независимо друг от друга, то нельзя определить, кто из них получает что раньше. У каждого из них своё локальное время.
4. Понятие однородности времени и пространства в ООП не имеют никакого смысла, как бы красиво ни звучали эти слова. Особенно однородность относительно друг друга.
DG>вообще, вы с samius-ом рассматриваете самый просто вариант ООП (и что мне больше всего не нравится, что вы выдаете ее за догму, даже не понимая, какие ограничения вы при этом в нее заложили, который нет в самой концепции ООП)
Мы как раз всё понимаем. Это у вас в голове каша — прямо начиная с уровня базовых определений, и продолжая ошибками в элементарной логике.
DG>вы рассматриваете ООП лишь для случая: строго однородное строго атомарное строго непрерывное пространство,
Где вы это увидели? Никакого условия непрерывности пространства в ООП нету, как бы ни вводилось понятие пространства.
Понятие однородности я уже прокомментировал выше. DG>условное время (в виде лишь условной последовательности сообщений), есть строго полное знание ("мир" знает всё про всех), все состояния строго однозначные (нет неопределенных состояний)
Как раз такое время, как я описал — это самое минималистичное определение времени, при котором ООП ещё работает. Поверх него можно вводить более сильные модели времени — например, с глобальным временем или понятием "длительности".
Никакого требования "мира" знать всё про всех нету — это вы придумываете что-то своё.
DG>и соответственно, всех этих ограничений нет в самой модели ООП, а вы их накладываете сами.
Вы не понимаете, что такое "ограничение", и что такое "накладывать". Вся математика строится на том, что изучает минимальные модели. Вот мы вам пытаемся рассказать, что такое минимальное ООП. А вы пытаетесь то выкинуть из него неотъемлемые свойства (думая, что что-то добавляете), то засовываете в него то, без чего ООП работает.
DG>в данном коде, с точки зрения клиента ответ приходит раньше, чем сообщение отправлено.
С чего это вы взяли? Ничего подобного. Вы слишком вольно общаетесь с терминологией. Pong() здесь — никакой не ответ. Если хотите, я вам этот пример разберу поподробнее. DG>это я к тому, что даже все ООП-языки, которые существуют, работают в рамках намного более полной ООП-модели, чем та, на которую вы ссылаетесь.
Конечно. Реальные языки работают со значительно более сложными моделями. Но они получаются из базовой модели ООП.
Для того, чтобы разобрать кашу в голове, нужно разделить всё, что можно разделить. Например, изучить в совершенстве базовую модель. Потом из этих мелких запчастей можно начинать строить более полезные модели.
DG>в данном коде, чтобы понять в чем проблема — требуется уже вводит такое понятие как неатомарность операции отправки сообщения.
Вы хотели сказать "неатомарность операции получения ответа на сообщение". Если что, в вашем примере есть минимум четыре момента времени (это если никаких сообщений более не происходит).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.