Здравствуйте, DarkGray, Вы писали:
S>>Вот и я об этом. Сначала вы утверждали что я слишком узко понимаю ООП, теперь оказалось что вы его понимаете шире чем оно есть. Если бы вы начали со слов "давайте представим расширенное ООП2, где идентичность не нужна", то возражать было бы нечего.
DG>я хочу от тебя, чтобы ты не просто ссылался на ООП в формате я верю: что с точки зрения ООП — это неверно, а доказал что это неверно.
DG>например, в ООП не вводится понятия времени. DG>поэтому если ввести формальную функцию идентичности как: идентичность объектов определяется как идентичность состояния объектов в моменты времени t, когда g(t) > 0.
В момент компиляции мы не знаем даже то, сколько объектов будет создано, не говоря уже о том, какие из ссылок будут указывать на один и тот же объект.
DG>и докажи (или покажи) какому базисному утверждению ООП — это противоречит.
Противоречит тому что идентичность позволяет отличать объекты (безотносительно времени t).
DG>при этом функция идентичности есть — вот она, выше.
Это не идентичность, т.к. она не позволяет отличать объекты.
Давай еще раз, более развернуто
SomeObject *a = GetSomeObject();
SomeObject *b = GetSomeObject();
if (rnd.next() > 0.5)
a = b;
Покажи мне, как будет выглядеть определение того, ссылаются ли переменные на один объект во время компиляции.
if там вообще-то лишний, потому как неизвестно, вернет ли GetSomeObject один и тот же объект, или каждый раз разные, или она будет возвращать один и тот же не более 3х раз... Но пусть if будет хохмы для.
Та функция идентичности, что ты привел, ничего не говорит о идентичности экземпляров SomeObject
Здравствуйте, samius, Вы писали:
S>>>Хорошо, пусть будет объект, инициализированный значением этого литерала. Но i — это не объект. Это идентификатор.
V>>Для случая оперирования по значению, это одно и то же. S>Возражаю. Идентификатор один, значения разные. Уже это дает повот делать различия.
Нет никакого идентификатора в рантайм, это условное обозначение времени компиляции, чтобы тебе было легче отличать один адрес от другого. Но сама сущность "переменная" никуда не девается в рантайм, в отличие от идентификатора. И что ты подразумеваешь под "значения разные"? Конечно, с т.з. ООП, объект может иметь разные состояния, поясни, где ты видишь противоречие? Неужели только из-за того факта, что можно целиком заменить состояние объекта? Но ведь можно так же не целиком даже для объектов, хранящихся по-значению на стеке (модифицируя только часть полей или вызывая методы, модицифицирующие только часть полей). И точно так же можно целиком изменить состояние объекта, хранящегося на куче, т.е. по неизвестному адресу времени компиляции, поэтому для доступа к которому мы используем переменные ссылочного типа. Абсолютно одинаковые сценарии изменения состояния доступны в обоих случаях.
Что касается переменных примитивных типов, то стоит таки обратиться к определению ООП, данное Алланом Кеем, но целиком, а не только к первому предложению. Конечно, он вводит понятие "примитивных" типов, ибо где-то должна быть точка отсчетов для построения более сложных композиций из простых. Но экземплярам этих "примитивных" типов никто не мешает быть полноценными объектами. Разница лишь в том, составные это типы или нет, т.е. какова размерность пространства состояний объекта. Согласись, это отличие не означает неприменимости парадигмы ООП к таким примитивным типам. Например, любой объект, имеющий всего одно не ссылочное поле примитивного типа, хоть и является строго говоря составным, но демонстрирует все характеристики точно такого же примитивного типа в плане его пространства состояний. Скажу больше, такие объекты обычно делают для ограничения исходного пространства состояний примитивного типа, т.е. протягивая некую зависимость тип-область_значений в систему типов программы.
Ну и, возвращаясь к идентификатору. Есть такое понятие identity, это не есть идентификатор. В рамках одной программы identity объекта есть его адрес (даже если предвидеть возражение насчет операций GC по передвижкам объектов, то ведь он подменяет так же все ссылки на него, в т.ч. ref ссылки на внутренние поля объектов, поэтому такая процедура прозрачна для программиста). А в распределенных средах как identity выступает обычно некий токен из байт или подмножества байт (символов), который опять же нужен для перевода на каждой стороне этого токена в адрес объекта.
I>>>>А употребленное тобой "имя переменной" это в терминах чего было? S>>>Хорошо, пусть будет "идентификатор".
V>>Имя переменной тоже неплохо, в чем проблема? По определению, переменная в ЯП — это именованный адрес. S>ЯП — это другой уровень. Я говорил в терминах ООП.
ООП полностью зиждется на процедурном подходе и использует его аппарат для своей реализации. Семантику сущности "переменной" он не изменяет ни разу. Да и какая разница, хранится ли объект на куче, на стеке или как поле другого объекта (т.е. непосредственно по значению). Расположение объекта в куче не дает этому сценарию никаких отличий в плане парадигмы ООП, в сравнении с остальными способами расположения объектов. Разница есть, например, для GC в управляемых средах, так же как есть ограничения (например, невозможно получить и сохранить safe-ссылку на поле внутри объекта), но это никакого отношения к самому ООП не имеет.
Здравствуйте, samius, Вы писали:
S>И все-таки в ООП нет понятия переменной. Но есть идентификаторы объектов, ссылки на объекты.
Полностью неверно. И далее везде по ветке тоже.
Без сущности "переменная" ООП даже не взлетит. Ссылки на объекты, как и на любые другие типы, бывают: прямые и разной степени косвенности. Например, конкретно в дотнете, переменные ссылочного типа — это непрямые ссылки на объекты, а косвенные, т.е. требующие разыменования адреса во время исполнения.
Сорри за приводимый нижее ликбез уровня конца 1-го курса профильной специальности, но прочитаная ветка удивила более, чем полностью...
Рассмотрим value-типы дотнета.
1. статическая переменная — прямая ссылка (абсолютный адрес);
2. член ref-типа — абсолютное смещение относительно адреса объекта;
3. член value-типа — абсолютное смещение относительно адреса объекта. Если адрес объекта известен в compile-time, то смотри 1. (и далее рекурсивно для любых вложений тоже);
4. локальная переменная — абсолютное смещение относительно адреса текущего фрейма стека.
Боксированные value-type ничем не отличаются от экземпляров ref-типов. Отличия есть при размещении их по-значению, ввиду ограничений на наследование, которое позволило в итоге сэкономить и не хранить с value-типами служебную информацию, типа ссылок на дескриптор типа (т.к. он достоверно известен в compile-time).
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
S>>>>Хорошо, пусть будет объект, инициализированный значением этого литерала. Но i — это не объект. Это идентификатор.
V>>>Для случая оперирования по значению, это одно и то же. S>>Возражаю. Идентификатор один, значения разные. Уже это дает повот делать различия.
V>Нет никакого идентификатора в рантайм, это условное обозначение времени компиляции, чтобы тебе было легче отличать один адрес от другого. Но сама сущность "переменная" никуда не девается в рантайм, в отличие от идентификатора. И что ты подразумеваешь под "значения разные"?
Да, неточно выразился. ООП оперирует ссылками на объекты. Но оно и не знает что такое компиляция и время компиляции. Идентификаторы позволяют нам отличать ссылки в ЯП, но это тоже не термин ООП.
Значения — это чуть более обще, чем объект. Пусть будет объект. Не против рассматривать значения примитивных типов в качестве объекта. Но призываю различать идентификатор (i), ссылку (переменную) и значение(объект). V>Конечно, с т.з. ООП, объект может иметь разные состояния, поясни, где ты видишь противоречие? Неужели только из-за того факта, что можно целиком заменить состояние объекта?
Я просто отличаю состояния объекта от состояния переменной. Переменная позволяет целиком заменить объект, на который она ссылается (как ссылка в терминах ООП). Но она и позволяет изменять состояние объекта, сохраняя идентичность объекта. V>Но ведь можно так же не целиком даже для объектов, хранящихся по-значению на стеке (модифицируя только часть полей или вызывая методы, модицифицирующие только часть полей). И точно так же можно целиком изменить состояние объекта, хранящегося на куче, т.е. по неизвестному адресу времени компиляции, поэтому для доступа к которому мы используем переменные ссылочного типа. Абсолютно одинаковые сценарии изменения состояния доступны в обоих случаях.
только ООП не знает что такое куча и стек. И неважно, изменяем ли мы состояние объекта целиком или частично. Когда присваиваем переменной новое значение — она ссылается на новый объект. Если мы вызываем метод объекта, который целиком и полностью меняет свое состояние — то это изменение состояния объекта.
V>Что касается переменных примитивных типов, то стоит таки обратиться к определению ООП, данное Алланом Кеем, но целиком, а не только к первому предложению. Конечно, он вводит понятие "примитивных" типов, ибо где-то должна быть точка отсчетов для построения более сложных композиций из простых. Но экземплярам этих "примитивных" типов никто не мешает быть полноценными объектами. Разница лишь в том, составные это типы или нет, т.е. какова размерность пространства состояний объекта. Согласись, это отличие не означает неприменимости парадигмы ООП к таким примитивным типам. Например, любой объект, имеющий всего одно не ссылочное поле примитивного типа, хоть и является строго говоря составным, но демонстрирует все характеристики точно такого же примитивного типа в плане его пространства состояний. Скажу больше, такие объекты обычно делают для ограничения исходного пространства состояний примитивного типа, т.е. протягивая некую зависимость тип-область_значений в систему типов программы.
С этим согласен.
V>Ну и, возвращаясь к идентификатору. Есть такое понятие identity, это не есть идентификатор. В рамках одной программы identity объекта есть его адрес (даже если предвидеть возражение насчет операций GC по передвижкам объектов, то ведь он подменяет так же все ссылки на него, в т.ч. ref ссылки на внутренние поля объектов, поэтому такая процедура прозрачна для программиста).
Есть такое понятие как object identity. Оно определено достаточно абстрактно. А вот то что в качестве identity в конкретных ООП системах используется storage location — это уже частный случай. Отношение между идентификатором и identity следующее: идентификатор — это имя ссылки, которая ссылается на объекты.
V>А в распределенных средах как identity выступает обычно некий токен из байт или подмножества байт (символов), который опять же нужен для перевода на каждой стороне этого токена в адрес объекта.
Естественно. Только надо отличать, где object identity разрабатываемой системы, а где identity, которой ЯП обеспечивает свое отношение к ООП. Например, в спецификации C# четко сказано, что identity ссылочных типов основывается на storage location, а identity значимых типов — на побитовом соответствии содержимого. Но это не значит, что identity любых систем, написанных на C#, должна быть именно такой.
V>>>Имя переменной тоже неплохо, в чем проблема? По определению, переменная в ЯП — это именованный адрес. S>>ЯП — это другой уровень. Я говорил в терминах ООП.
V>ООП полностью зиждется на процедурном подходе и использует его аппарат для своей реализации. Семантику сущности "переменной" он не изменяет ни разу.
Только в ООП не переменная а ссылка. И не факт что у ссылки есть имя. Переменная — это реализация уровня ЯП понятия ссылка из ООП. V>Да и какая разница, хранится ли объект на куче, на стеке или как поле другого объекта (т.е. непосредственно по значению). Расположение объекта в куче не дает этому сценарию никаких отличий в плане парадигмы ООП, в сравнении с остальными способами расположения объектов. Разница есть, например, для GC в управляемых средах, так же как есть ограничения (например, невозможно получить и сохранить safe-ссылку на поле внутри объекта), но это никакого отношения к самому ООП не имеет.
Да.
Здравствуйте, Sinclair, Вы писали:
S>Вот, например, в следующем коде — ровно одна переменная:
int a1 = 1;
int&a2 = a1;
S>А имён у неё две.
Неверно. Есть одно значение, и две переменных, на него ссылающихся. Если приведенный снипет кода описывает глобальные переменные, то a1 — это непосредственная адресация, a2 — прямая (т.к. ссылка на адрес времени компиляции). Если же это локальные (стековые) переменные, то a1 — это относительная адресация, a2 — разновидность косвенной (относительная и +1 уровень косвенности).
А теперь сделаем такой маленький фокус:
double a1 = 1;
double & a2 = a1;
Ввиду того, что double в опкодах современных процов не может быть адресован непосредственно, даже для случая глобального снипета мы получили прямую адресацию и косвенную. Ввиду того, что непосредственная адресация — это скорее бонус для очень небольшого типа данных, в общем случае я предпочитаю подразумевать этот второй вариант, т.к. он точно такой же для любых составных типов, коих оперируемых обычно на порядки больше.
Поэтому, здесь две косвенные ссылки на одно значение (т.е. на один объект, если уж про ООП речь):
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
S>>И все-таки в ООП нет понятия переменной. Но есть идентификаторы объектов, ссылки на объекты.
V>Полностью неверно. И далее везде по ветке тоже.
Далее по ветке все абсолютно не про ООП в общем виде. Может быть про ООП, но про его частное исполнение.
V>Без сущности "переменная" ООП даже не взлетит. Ссылки на объекты, как и на любые другие типы, бывают: прямые и разной степени косвенности. Например, конкретно в дотнете, переменные ссылочного типа — это непрямые ссылки на объекты, а косвенные, т.е. требующие разыменования адреса во время исполнения.
Переменная — это реализация понятия ссылка из ООП. Само ООП не знает, что такое переменная.
V>Сорри за приводимый нижее ликбез уровня конца 1-го курса профильной специальности, но прочитаная ветка удивила более, чем полностью...
V>Рассмотрим value-типы дотнета. V>1. статическая переменная — прямая ссылка (абсолютный адрес);
Переменная это storage, а не ссылка. В C++ нового стандарта теперь несколько по-другому, но что касается дотнета, то там переменная — это однозначно место в памяти, о чем написано в спеке. V>2. член ref-типа — абсолютное смещение относительно адреса объекта; V>3. член value-типа — абсолютное смещение относительно адреса объекта. Если адрес объекта известен в compile-time, то смотри 1. (и далее рекурсивно для любых вложений тоже); V>4. локальная переменная — абсолютное смещение относительно адреса текущего фрейма стека.
Все-таки я бы различал место и смещение. Смещение задает позицию места относительно места объекта.
V>Боксированные value-type ничем не отличаются от экземпляров ref-типов. Отличия есть при размещении их по-значению, ввиду ограничений на наследование, которое позволило в итоге сэкономить и не хранить с value-типами служебную информацию, типа ссылок на дескриптор типа (т.к. он достоверно известен в compile-time).
V>Рассмотрим value-типы дотнета. V>1. статическая переменная — прямая ссылка (абсолютный адрес); V>2. член ref-типа — абсолютное смещение относительно адреса объекта; V>3. член value-типа — абсолютное смещение относительно адреса объекта. Если адрес объекта известен в compile-time, то смотри 1. (и далее рекурсивно для любых вложений тоже); V>4. локальная переменная — абсолютное смещение относительно адреса текущего фрейма стека.
Спасибо за ликбез.
Можно поинтересоваться, откуда взялись эти замечательные предположения?
Вот, например, "статическая переменная", как известно из букваря, используется в дотнете при помощи инструкции ldsfld/ldsflda. Откуда в MSIL возьмётся абсолютный адрес — непонятно.
Вообще, понятие "адрес" в спецификации дотнета применимо исключительно к unmanaged pointer types, см. секцию 8.9.2.
Понятие "абсолютное смещение" — это, надо полагать, результат вычитания двух поинтеров. Применимо только к unmanaged pointers, unverifiable. То есть, в легальной дотнет-программе понятие смещения использовать нельзя.
Понятие "адреса объекта" в спецификации дотнета не используется. Понятие "адрес текущего фрейма стека" — тоже.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, DarkGray, Вы писали:
DG>например, в ООП не вводится понятия времени.
В ООП время вводится неявно — как последовательность состояний и сообщений.
Думать, что его нет, не надо.
Если бы в ООП совсем не было времени, то невозможно было бы определить, какое из сообщений приходит раньше других. И понятие состояния не имело бы смысла.
Чего в ООП-шном времени нет "из коробки", так это понятие длительности.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
S>>Да, неточно выразился. ООП оперирует ссылками на объекты.
V>Именно, как и процедурный подход ссылками на экземпляры типов. Но ссылки-то разные бывают: http://www.rsdn.ru/forum/philosophy/4505309.1.aspx
Я призываю различать ссылки ЯП от ссылок ООП.
Но даже ссылка ЯП не всегда есть переменная. Так например, согласно новой спеке C++, при объявлении ссылки на статические мемберы объекта переменная не вводится. Ссылка есть, а переменной нет. Считать их одним и тем же — слишком наивно.
V>И отсюда все ниже по ветке с т.з. моего ИМХО лучше бы вырезать с сайта, пока не поздно.
Поздно для чего?
DG>>например, в ООП не вводится понятия времени. S>В ООП время вводится неявно — как последовательность состояний и сообщений. S>Думать, что его нет, не надо.
отлично.
теперь обоснуй почему на основе такого определения времени нельзя использовать вот такую функцию для identity:
идентичность объектов определяется как идентичность состояния объектов в моменты времени t, когда g(t) > 0.
ps
в моделях: последовательность событий, которые как будто время, и время — это совсем разные вещи.
Здравствуйте, samius, Вы писали:
S>Так например, согласно новой спеке C++, при объявлении ссылки на статические мемберы объекта переменная не вводится. Ссылка есть, а переменной нет. Считать их одним и тем же — слишком наивно.
Почему? Надо ясно представлять, что есть ссылка в С++. Это синоним следующего:
T * const variable = someExpr;
Итого, "ссылка" в С++ это переменная константного типа (повторю, не путать с указателями/ссылками НА константный тип), а раз так, т.е. раз модификация значения самой переменной невозможна, то синтаксис можно упростить, например, не пользовать operator->. Зачем это надо? Это дало некую свободу действий по применению шаблонов, где мы можем один и тот же шаблон (т.е. кодогенератор) использовать как для ссылочных типов, так и для оперируемых по-значению. Очень удобно. Без этого техника шаблонов потеряла бы приличную долю своей мощи.
, имеем константное значение адреса, которое известно в compile-time. Выделяется под этот адрес ячейка памяти или нет, семантически неважно, как и в этом выражении:
const int i = 42;
Пока адрес переменной i не берем, то память под переменную не выделяется. Если берем, то выделяется память, хотя используется только там, где нужен именно адрес, а где оперируем значением i непосредственно, все-равно это константа времени компиляции (можешь проверить, хакнув константность переменной через const_cast и записав туда другое значение). Считай это некоей оптимизацией, которая целиком на совести компилятора, ведь происходит много других похожих оптимизаций, с распространением констант времени компиляции, главное что сохраняется семантика.
К чему это я? Просто у ссылок по стандарту нельзя взять адрес, т.е. описанный тобой эффект де-факто присутствует изначально, и его прописали в стандарте, наконец. По мне — так на здоровье, коль исходная семантика не ломается.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
S>>Так например, согласно новой спеке C++, при объявлении ссылки на статические мемберы объекта переменная не вводится. Ссылка есть, а переменной нет. Считать их одним и тем же — слишком наивно.
V>Почему?
По спецификации.
V>Надо ясно представлять, что есть ссылка в С++. Это синоним следующего: V>T * const variable = someExpr;
Нет, не синоним. Даже не похоже. Адрес ссылки взять нельзя, обязательно надо инициировать...
V>Не путать с этим: V>T const * variable = someExpr;
V>(Обе декларации комбинаторно порождают 4 варианта)
Я достаточно знаком с C++ что бы не путать такие вещи.
V>Итого, "ссылка" в С++ это переменная константного типа (повторю, не путать с указателями/ссылками НА константный тип), а раз так, т.е. раз модификация значения самой переменной невозможна, то синтаксис можно упростить, например, не пользовать operator->. Зачем это надо? Это дало некую свободу действий по применению шаблонов, где мы можем один и тот же шаблон (т.е. кодогенератор) использовать как для ссылочных типов, так и для оперируемых по-значению. Очень удобно. Без этого техника шаблонов потеряла бы приличную долю своей мощи.
"Итого, "ссылка это переменная" ниоткуда не следует пока.
V>Вернемся к ссылокам на статические члены классов и на глобальные переменные. С учетом вышесказанного и по этой ссылке тоже http://www.rsdn.ru/forum/philosophy/4505309.1.aspx
, имеем константное значение адреса, которое известно в compile-time. Выделяется под этот адрес ячейка памяти или нет, семантически неважно, как и в этом выражении: V>const int i = 42;
V>Пока адрес переменной i не берем, то память под переменную не выделяется. Если берем, то выделяется память, хотя используется только там, где нужен именно адрес, а где оперируем значением i непосредственно, все-равно это константа времени компиляции (можешь проверить, хакнув константность переменной через const_cast и записав туда другое значение). Считай это некоей оптимизацией, которая целиком на совести компилятора, ведь происходит много других похожих оптимизаций, с распространением констант времени компиляции, главное что сохраняется семантика.
Выделяется ли ячейка или нет, неважно. Но семантически важно что мы можем взять адрес этой ячейки.
V>К чему это я? Просто у ссылок по стандарту нельзя взять адрес, т.е. описанный тобой эффект де-факто присутствует изначально, и его прописали в стандарте, наконец. По мне — так на здоровье, коль исходная семантика не ломается.
Все эти рассуждения не приводят к тождеству понятий ссылка и переменная даже в рамках С++.
Более того, устоявшимся и наиболее употребимым является выражение "ссылка на переменную", а не "ссылочная переменная".
Здравствуйте, DarkGray, Вы писали:
DG>теперь обоснуй почему на основе такого определения времени нельзя использовать вот такую функцию для identity: DG>идентичность объектов определяется как идентичность состояния объектов в моменты времени t, когда g(t) > 0.
Потому что на основе такого определения нам не удастся определить, какому объекту мы отдаём сообщения. DG>в моделях: последовательность событий, которые как будто время, и время — это совсем разные вещи.
Да ладно? Ну расскажите мне, что же такое время в моделях.
Я просто компьютерным наукам не обучен, кроме университетского курса математики и физики ничего не знаю.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, DarkGray, Вы писали:
DG>отлично. DG>теперь обоснуй почему на основе такого определения времени нельзя использовать вот такую функцию для identity: DG>идентичность объектов определяется как идентичность состояния объектов в моменты времени t, когда g(t) > 0.
Предположим, есть два объекта которые идентичны согласно твоему определению идентичности.
Ответь пожалуйста на три вопроса:
Можно ли в момент времени t+1 послать одному объекту сообщение A, а второму сообщение Б ?
Если да, то каким образом это возможно, т.к. в момент времени t и все предыдущие эти два объекта идентичны ?
Если нет, то нахрена нам нужна такая идентичность ?
Здравствуйте, samius, Вы писали:
S>>>Так например, согласно новой спеке C++, при объявлении ссылки на статические мемберы объекта переменная не вводится. Ссылка есть, а переменной нет. Считать их одним и тем же — слишком наивно.
V>>Почему? S>По спецификации.
Ну коль синтаксис другой, то и спецификации дополнительные нужны понятно.
Это не ответ. Давай еще раз, чем ссылка отличается от любой другой константной переменной?
V>>Надо ясно представлять, что есть ссылка в С++. Это синоним следующего: V>>T * const variable = someExpr; S>Нет, не синоним. Даже не похоже. Адрес ссылки взять нельзя, обязательно надо инициировать...
Адрес нельзя брать по спецификации, иначе бы невозможно было бы использование operator. взамен operator->.
Константы надо обязательно инициализировать при объявлении, итого остается только отличие в operator->.
Насчет инициализации... обязательно инициализировать надо любую константу.
И да, я могу привести пример, где даже ссылки на статические члены всё равно будут переменными (т.е. занимать память):
extern int & i; // заметь, без инициализации
А если ссылка импортируется из DLL, то еще и с доп. переходником, т.е. +1 уровню косвенности. Итого, под эту ссылку будет выделено целых два слота памяти, длиной в машинное слово, вместо ни одной.
Так же как могу привести пример, где ссылка на нестатические члены никогда не будет занимать лишней памяти:
void main() {
int i = 0;
int ref_i = i;
std::cout << ref_i << std::endl;
}
ref_i будет вычислена в compile-time, как и любое вычислимое в compile-time выражение, напр:
const int i = 42;
const int j = i + 1;
S>Выделяется ли ячейка или нет, неважно. Но семантически важно что мы можем взять адрес этой ячейки.
Почему у ссылки отсутствует взятие адреса уже сказал. Можно вернуться к пред. посту.
V>>К чему это я? Просто у ссылок по стандарту нельзя взять адрес, т.е. описанный тобой эффект де-факто присутствует изначально, и его прописали в стандарте, наконец. По мне — так на здоровье, коль исходная семантика не ломается. S>Все эти рассуждения не приводят к тождеству понятий ссылка и переменная даже в рамках С++.
Дык, и константа не равна тождественно обычной переменной. По стандарту, на усмотрение компилятора отводится решение — где и как выделять память под константы и выделать ли вообще. ИМХО, полностью аналогично. Например, адреса констант, требующих память для хранения в сегменте данных (т.н. литералов), компилятор имеет право "склеивать", т.е. вместо десяти одинаковых констант иметь одну, а для обычных переменных — не имеет права. Именно поэтому я вижу аналогичное поведение со случаем константного указателя с точностью до operator-> (т.е. невозможностью взять адрес как раз для того, чтобы обеспечить работоспособность отсутствия небходимости operator->).
S>Более того, устоявшимся и наиболее употребимым является выражение "ссылка на переменную", а не "ссылочная переменная".
Не слышал такого, бо ссылка может быть и на объект в куче.
Есть просто тип данных — ссылка, не надо ничего лишнего гадать, надо понимать, что это константный адрес целевого объекта. Да, иногда этот адрес может быть известным во время компляции, если адрес целевого объекта тоже известен во время компиляции. Именно из-за этого я не вижу противоречий и какого-то особенного случая, отличного от других случаев констант времени компиляции.
Здравствуйте, vdimas, Вы писали:
L>>Да, тип Int32 — неизменяемый. Отсутствие/наличие const тут погоды не делает, т.к. этот модификатор относится не к типу, а к переменной.
V>Дожились...
Нет, простой int вроде.
V>Там в переменной целиком хранится состояние объекта, так что не передергивайте.
Вы путаете понятия разных уровней.
Переменная — понятие конкретного языка программирования, оно служит для идентификации какого-то значения, используемого в прграмме.
Поэтому в каком-то смысле переменная является "ссылкой".
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
V>>>Почему? S>>По спецификации.
V>Ну коль синтаксис другой, то и спецификации дополнительные нужны понятно. V>Это не ответ. Давай еще раз, чем ссылка отличается от любой другой константной переменной?
Ок, насыплю побольше
* указатель может ссылаться на NULL
* невозможно взять адрес ссылки (уже было, но для полноты списка)
* невозможно объявить ссылку на ссылку как указатель на указатель
* у ссылок нет арифметики (в отличии от константного указателя)
* переменная имеет адрес и размер, а ссылка лишь ссылается на место в памяти, предоставленное некой переменной
* в отличии от указателя, ссылка продлевает время жизни временного объекта
V>>>Надо ясно представлять, что есть ссылка в С++. Это синоним следующего: V>>>T * const variable = someExpr; S>>Нет, не синоним. Даже не похоже. Адрес ссылки взять нельзя, обязательно надо инициировать...
V>Адрес нельзя брать по спецификации, иначе бы невозможно было бы использование operator. взамен operator->.
Неудовлетворительное объяснение. В отличии от указателя (для которого определен оператор ->), ссылка представляет собой псевдоним объекта. Потому, что бы не применялось к ссылке, оно на самом деле применяется к значению, которое лежит в месте памяти, на которое ссылается ссылка. V>Константы надо обязательно инициализировать при объявлении, итого остается только отличие в operator->.
Константный указатель можно проинициализировать NULL-ом.
V>Насчет инициализации... обязательно инициализировать надо любую константу. V>И да, я могу привести пример, где даже ссылки на статические члены всё равно будут переменными (т.е. занимать память): V>extern int & i; // заметь, без инициализации
Еще бы... Но это не объявление ссылки. Это объявление того, что ссылка объявлена в другом месте.
V>А если ссылка импортируется из DLL, то еще и с доп. переходником, т.е. +1 уровню косвенности. Итого, под эту ссылку будет выделено целых два слота памяти, длиной в машинное слово, вместо ни одной.
А это не важно, т.к. взять адреса этих слотов не представляется возможным на уровне языка.
V>Так же как могу привести пример, где ссылка на нестатические члены никогда не будет занимать лишней памяти: V>
V>void main() {
V> int i = 0;
V> int ref_i = i;
V> std::cout << ref_i << std::endl;
V>}
V>
А где ссылка? V>ref_i будет вычислена в compile-time, как и любое вычислимое в compile-time выражение, напр:
Меня на данном уровне обсуждения мало интересуют оптимизации компилятора, который при эквивалентности резульата волен делать что угодно. На уровне языка и i и ref_i — переменные. Я могу взять их адреса и вывести в cout.
S>>Все эти рассуждения не приводят к тождеству понятий ссылка и переменная даже в рамках С++.
V>Дык, и константа не равна тождественно обычной переменной. По стандарту, на усмотрение компилятора отводится решение — где и как выделять память под константы и выделать ли вообще. ИМХО, полностью аналогично. Например, адреса констант, требующих память для хранения в сегменте данных (т.н. литералов), компилятор имеет право "склеивать", т.е. вместо десяти одинаковых констант иметь одну, а для обычных переменных — не имеет права. Именно поэтому я вижу аналогичное поведение со случаем константного указателя с точностью до operator-> (т.е. невозможностью взять адрес как раз для того, чтобы обеспечить работоспособность отсутствия небходимости operator->).
Усмотрение компилятора в отношении ООП меня совершенно не волнуют. Я вообще могу (теоретически) допустить, что компилятор может произвести graph rewriting с редукцией и не оставить ничего, что бы напоминало об исходном коде. Ни узнаваемых структур данных, ни переменных... Это не заставит меня считать что в исходном коде на C++ не стало структур данных и переменных.
S>>Более того, устоявшимся и наиболее употребимым является выражение "ссылка на переменную", а не "ссылочная переменная".
V>Не слышал такого, бо ссылка может быть и на объект в куче.
может. Ссылка она вообще на место. V>Есть просто тип данных — ссылка, не надо ничего лишнего гадать, надо понимать, что это константный адрес целевого объекта. Да, иногда этот адрес может быть известным во время компляции, если адрес целевого объекта тоже известен во время компиляции. Именно из-за этого я не вижу противоречий и какого-то особенного случая, отличного от других случаев констант времени компиляции.
Важное отличие в том, что объявление переменной приводит к созданию storage location для переменной, а объявление ссылки — нет. При этом неважно, выкинет компилятор это storage location, как в случае с ref_i, или нет.