|
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
|
|
Как применить ref и out для ссылок на объекты07.09.2012, 14:21. Показов 23690. Ответов 56
Метки нет (Все метки)
Помогите пожалуйста разобраться новичку. Читаю шилдта, никак не могу въехать.... С применением Ref & out для переменных типа значений все предельно ясно. А вот при для объектов не могу понять...
Как вижу все это я: Типы значений: при передаче методу параметр получает копию значения аргумента. Соответственно, любые изменения в методе приводят к изменению копии аргумента, а значит, сам аргумент не изменяется. Все это исправляется при использования ref&out. Ссылочный тип: при передаче методу параметр получает копию ссылки на объект. Т.е. сама ссылка передается по значению. Получается, наш объект теперь имеет "псевдонимы", и его можно изменять из метода. Но что происходит при использовании ref с объектом??? Шилдт приводит пример с методом Swap, в котором изменяются ссылки на объекты.... (с 228) Кто бы мне объяснил весь процесс по пунктам... а то никак не могу понять, что вообще там происходит. Фраза: если модификаторы ref или out указывают на ссылку, то сама ссылка передается по ссылке - убила наповал))) Спасибо заранее
0
|
|
| 07.09.2012, 14:21 | |
|
Ответы с готовыми решениями:
56
Описать класс "Вектор" для хранения ссылок на объекты Как можно в textarea применить ::first-line, или как к первой строки применить стиль, внутри данного элемента |
|
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
|
|
| 07.09.2012, 17:10 [ТС] | |
|
В продолжение моего вопроса:
1. Существует некая ячейка памяти с адресом 0хFF, в которой хранится объект с именем Петя. 2. Существует ссылка на него, расположенная по адресу 0хАА. При вызове метода NoRef создается ячейка памяти, хранящая значение 0хFF (т.е. копия ссылки) - это как я понимаю и есть параметр метода. При вызове метода Ref создается ячейка памяти, получающая значение 0хАА (получается ссылка на ссылку и также являющаяся параметром метода) 3. Далее существует некая ячейка памяти с адресом 0xDD, в которой создается объект с именем Вася. При вызове метода NoRef параметру (с текущим значением 0xFF, указывающему на объект с именем Петя) присваивается значение 0хDD. Теперь параметр хранит ссылку на объект с именем Вася. естественно, ячейка памяти по адресу ОхАА не изменяется и все также содержит значение 0хFF. При вызове же метода Ref, ячейка памяти, прежде хранящая значение 0хAA, получает новое значение 0хDD. Отныне она хранит ссылку на объект с именем Вася. Так в чем же разница????? Ведь при вызове метода Ref ячейка памяти расположенная по адресу 0хАА и хранящая 0хFF не изменяется ни в том, ни в том случае... Где ошибка в моей логике???
0
|
|
|
51 / 38 / 5
Регистрация: 14.01.2012
Сообщений: 127
|
||||||||
| 07.09.2012, 21:54 | ||||||||
|
temcha,
1. Существует некая ячейка памяти с адресом 0хFF, в которой хранится массив интов 2. НЕ существует ссылка на него, в том смысле, что переменная типа int[] возвращает именно объект, массив:
При вызове метода Ref метод в итоге работает с ячейкой по адресу 0хFF. Вообще, имхо, думать, что у нессылочных типов есть ссылка на них - бессмысленно. Лучше считать что переменная - это есть ячейка в памяти, а не ссылка на ячейку для нессылочных типов или ссылка на ссылку для ссылочных. При использовании ref и out переменная, переданная в метод извне - это та же переменная принятая как параметр в методе, хотя они могут по-разному называться. То что ref создает ссылку на объект - как бы верно, но в методе мы получаем ту же, уже готовую ячейку памяти, только работаем с этой ячейкой памяти уже через другую переменную. Т.е. в случае с ref лучше забить на то что это ссылка, так как эту ссылку никак нельзя использовать, ref применяется, можно сказать, для использования этой же переменной в методе. На мсдн для новых версий студии в определении ref присутствует слово ссылка, но в версии Visual Studio .NET 2003 не присутствует, мне оно кажется более верным:
0
|
||||||||
|
912 / 672 / 134
Регистрация: 01.03.2010
Сообщений: 1,279
|
||
| 07.09.2012, 22:22 | ||
|
0
|
||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||||||||||||||||||||||||||||||
| 08.09.2012, 11:48 | |||||||||||||||||||||||||||||||
Сообщение было отмечено как решение
Решение
temcha, как говорится, одна картинка стоит тысячи слов, потому вот вам несколько рисунков плюс многабукаф.
Вот код, который будет рассматриваться практически пошагово с точки зрения памяти:
Далее идет описание каждого участка кода и того, что происходит в памяти. Для удобства на изображениях в каждой ячейке памяти содержится четыре байта - в соответствии с размером регистра на x86. Дисклэймер: на изображениях приведено приблизительное расположение элементов в памяти, с точностью исключительно до того, что нас интересует. Потому любители пояснить о том, что ссылка - это не то же самое, что указатель, что она не указывает на адрес первого поля класса, что при инициализации объекта создается временная переменная, что помимо полей экземпляра в памяти хранится еще дополнительная информация для рантайма и т.д., могут расслабиться - пост не об этом. На начало запуска метода Main память имеет примерно такой вид: Далее выполняются вот эти строчки:
1. На стэке по адресу 0xFF выделяется место под переменную person, которое на данный момент содержит значение 0x00, то есть null. 2. В куче по адресам с 0x4C по 0x48 выделяется память под новый экземпляр класса Person, размер экземпляра равняется восьми байтам - 4 байта для ссылки на строку (Name) и 4 байта на целое число (Age). (тем, кто хочет сказать, что размер объекта по факту больше восьми байт - читать дисклэймер выше). 3. Адрес нового экземпляра в куче присваивается ссылке person, хранящейся в стеке по адресу 0xFF. То есть переменная person при компиляции будет заменена на 0xFF и значение этой ячейки, равное 0x4C, будет являться адресом экземпляра в куче. 4. Полю name присваивается адрес на новый экземпляр строки - в куче выделяется под нее память, записываются данные и адрес новой строки присваивается ссылке. Строки в .NET хранятся в UTF-16, потому на каждый символ выходит по два байта, то есть в каждой ячейке будет храниться по два символа. 5. По адресу 0x48 прописывается возраст Васи. После всех этих манипуляций память имеет примерно такой вид: Подытожим: а). person - это псевдоним для адреса 0xFF, по которому прописан адрес объекта в куче. б). person.Name - это псевдоним для адреса 0x4C, по которому прописана ссылка на строку - имя человека. в). person.Age - это псевдоним для адреса 0x48, где хранится возраст Васи. Далее происходит вызов метода NoRef
1. На стеке для аргумента "p" выделяется память по адресу 0xFB, куда записывается значение переменной "person", то есть значение ячейки памяти по адресу 0xFF. 2. Контекст выполнения переходит в метод NoRef. Итог: в куче лежит один объект, расположенный по адресу 0x4C. В стеке имеются две ячейки памяти по адресам 0xFF (псевдоним person) и 0xFB (псевдоним p), в которых хранится адрес этого объекта. Далее выполняется код метода NoRef:
2. Ссылка на этот объект записывается в стек по адресу 0xFB, имеющий псевдоним p. 3. В куче создается новый экземпляр строки по адресу 0x30 и этот адрес записывается в ячейку 0x3C, имеющую псевдоним p.Name. 4. Возраст Пети записывается в память по адресу 0x38, имеющий псевдоним p.Age. Вид на память аккурат перед завершением метода NoRef: Далее метод NoRef завершается, указатель стека возвращается на прежнюю позицию, тем самым выводя переменную p из области видимости. Так как p была единственной ссылкой на Петю, его судьба нам больше неизвестна - он стал кандидатом на уничтожение сборщиком мусора и в данный момент является котом Шрёдингера. Примерный вид на память сразу же после завершения метода NoRef: Свежесозданный Петя в памяти еще есть, а может быть уже и нет. Далее происходит переключение контекста на выполнение метода Ref.
После чего выполнение переходит в метод Ref и в байткоде везде, где используется переменная pref будет подставлен адрес 0xFF - всё просто.
1. В куче выделяется память под новый экземпляр класса Person. 2. Адрес нового объекта 0x2C записывается в память под псевдонимом pref, то есть в ячейку 0xFF 3. Так как на Васю больше никто не ссылается, он становится кандидатом на уничтожение сборщиком. 4. Как в предыдущие разы, создается новый экземпляр строки по адресу 0x20, туда записывается значение "Коля" и адрес новой строки записывается в ячейку 0x2C, носящую псевдонимы pref.Name и person.Name 5. По адресу 0x28 (псевдонимы pref.Age и person.Age) записывается возраст Коли. Вид на память перед завершением работы метода Ref: Метод завершается, псевдоним pref уничтожается, в итоге у ячейки 0xFF остается один-единственный псевдоним person. Обратите внимание, что в байткоде никаких псевдонимов не будет - будут тупо адреса памяти. Вид на память сразу после завершения работы метода Ref и перед завершением метода Main: Примерно так все и происходит. Пример, конечно, больше подходит под С++, т.к. в шарпе структура объектов сложнее, чем просто подряд идущие поля, а сама ссылка - не тупо указатель с адресом, а больше похожа на дескриптор объекта, но для описания общей картины, думаю, пойдет.
8
|
|||||||||||||||||||||||||||||||
|
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
|
|||||||||||
| 08.09.2012, 13:16 [ТС] | |||||||||||
|
ОГРОМНОЕ спасибо за прояснение ситуации.
Получается ссылка на ссылку в методе ref всего навсего добавление нового псевдонима на время действия метода? я раньше думал что это выделение ячейки памяти в стеке, которая будет хранить значение адреса исходной ссылки... и еще 2 вопросика: в С# массив является объектом, значит будет происходить все то же? и что происходит в памяти при присваивании объекта объекту? К примеру, мы в методе Ref сделали что то такое:
Person t;
0
|
|||||||||||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||||||||
| 08.09.2012, 13:25 | |||||||||
1
|
|||||||||
|
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
|
||||||
| 08.09.2012, 13:51 [ТС] | ||||||
|
Ув. kolorotur, по поводу второй части моего вопроса относительно присваивания, приведу кусочек кода на котором я пытаюсь разобраться что происходит при присваивании:
Не могли бы Вы пояснить что происходит с точки зрения памяти во время присваивания? Спасибо...
0
|
||||||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||||||||||
| 08.09.2012, 14:18 | |||||||||||
0
|
|||||||||||
|
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
|
|
| 08.09.2012, 16:39 [ТС] | |
|
да, с этим разобрался, спасибо. А где бы почитать о принципах сохранения информации в памяти?
0
|
|
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|
| 08.09.2012, 16:47 | |
|
Даже не знаю что посоветовать...
Я еще в ВУЗе проходил архитектуру ЭВМ (на примере MIPS, правда) - вдалбливали хорошо, до сих пор помню зачеты по ассемблеру. Добавлено через 26 секунд Дома может где-то книжка по предмету еще лежит - могу глянуть название. Правда, она на английском.
0
|
|
|
3 / 3 / 0
Регистрация: 03.06.2012
Сообщений: 38
|
|
| 08.09.2012, 18:01 | |
|
kolorotur,
Я правильно Вас понял? Допустим есть два объекта c псевдонимами ob1 и ob2 Далее, для примера: ob1 (адрес 0ХFF) ссылается на объект по адресу 0Х4С ob2 (адрес 0ХFB) ссылается на объект по адресу 0Х3С Теперь проведем такое действие ob1=ob2 Получаем, что адрес 0ХFB имеет теперь два псевдонима ob1 и ob2 а адрес 0ХFF и объект, на который он указывает по адресу 0Х4С попадают под раздачу мусорщика. Все верно?
0
|
|
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|
| 08.09.2012, 19:00 | |
|
Alexsis6911, да, все верно, только адрес 0xFF не попадает под раздачу мусорщика, т.к. хранится в стеке, а там мусорщик не прибирается. Просто до завершения контекста остается неиспользуемая "грязная" ячейка в стеке по адресу 0xFF.
1
|
|
|
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
|
|
| 08.09.2012, 19:26 [ТС] | |
|
буду благодарен, если скажешь название, пусть и на английском
0
|
|
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|
| 08.09.2012, 21:36 | |
|
David A. Patterson, John L. Hennessy. "Computer Organization and Design. The Hardware/Software Interface".
У меня старенькое издание, но она в декабре 2011 года обновилась до четвертого издания - ищите его. Вот ссылка на магазин издателя: http://store.elsevier.com/prod... ame=search В русском переводе, наверное, тоже где-то есть. Книжка очень мощная - рекомендую. Там от работы компиляторов до машинных инструкций и до построения логических схем ЦПУ (на их основе уже электрические схемы чертят, а дальше - только железо). Работа с памятью тоже рассматривается, причем работе с иерархиями памяти (кэш, виртуальная память и т.д.) отдельная глава отведена. Рассматриваются реальные модели памяти Интела и АМД. Ну и к задней корочке прицеплен сидюк с примерами, ассемблером, софтинками типа всяческих эмуляторов МИПСа и прочими вкусностями. Приятного чтения ![]() Не по теме: P.S. Надо будет у издательства деньжат за рекламу затребовать...
1
|
|
|
Master of Orion
|
||
| 08.09.2012, 22:45 | ||
|
kolorotur,
Не по теме: всегда, когда вижу новую книгу в сети (ну или совет), думаю "Неплохо бы скачать", а после фразы "сидюк с вкусностями" тут же приходит на ум "а может и купить"... :) Добавлено через 8 минут Вот нашел в магазине (модеры, звиняйте, но найти просто по поисковику было трудно): http://www.labirint.ru/books/317754/ Если все же затрете, описание
0
|
||
|
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
|
|
| 06.12.2016, 00:08 | |
|
kolorotur,
Почему у коллекций такого поведения нет?(они изменяются,даже если нет параметров ref / out)
0
|
|
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
||
| 06.12.2016, 01:04 | ||
|
ref/out позволяет изменять переменную. А добавляя/удаляя элементы из коллекции, вы меняете объект.
1
|
||
|
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
|
|||||||||||||||||
| 06.12.2016, 18:01 | |||||||||||||||||
|
Вот в этом онлайн компиляторе пробовал данный код:
1
|
|||||||||||||||||
|
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
|
|||||||||||||||||
| 07.12.2016, 19:54 | |||||||||||||||||
|
Почему мы не можем придать null объекту,ссылку которого,передали как параметр в методе? Опять же,если рассмотреть мой код:
Т.е. если в метод добавить этот код:
Другими словами, присвоение к Null или созданию нового объекта в контексте метода(в нашем случае это ModifyList),идет разыменовывание копии ссылки и соответственно работа уже проводиться со всем другим объектом?
0
|
|||||||||||||||||
|
.NET senior
441 / 359 / 137
Регистрация: 23.09.2016
Сообщений: 980
|
|
| 07.12.2016, 20:06 | |
|
Vasyan, насколько я помню, чтобы изменить значение поля, нужно напрямую записать значение, обращаясь к полю класса напрямую. Параметры в метод передаются по значению, то есть для ссылочных типов создается копия исходной ссылки (физически - выделяется новая область памяти, содержащая адрес объекта в куче). Если теперь изменить эту ссылку (создать новый объект и сохранить его адрес), то на оригинальную это никак не повлияет (и в то же самое время мы можем как угодно менять состояние объекта по этой ссылке).
0
|
|
| 07.12.2016, 20:06 | |
|
Перебор ссылок на объекты
Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
сукцессия 43. Вторая научная статья за месяц- прайминг и гатгил
anaschu 25.07.2026
две стороны одной монеты
|
Более приземисто - Эстафету хвоста в .cdl (деревья эстафеты в сад).
Hrethgir 24.07.2026
В будущем, после написания блока инверсии обхода дерева (эстафеты хвоста), я планирую вернуться к нашему прошлому разговору о том, обладают ли знания целеполаганием. Тогда я пришел к выводу, что. . .
|
Вот представьте что вам дали бессмертие.
kumehtar 24.07.2026
Вот представьте что вам дали бессмертие, ничего более не меняя. Вообще ничего, только бессмертие в нынешнем виде. Рады были бы? Что бы вы тут делали всё это время?
Никакой пенсии. Никакого нового. . .
|
сукцессия 41
anaschu 24.07.2026
Численная верификация бифуркации в агентной модели лесной сукцессии: от одного параметра к ансамблю
Автор: пользователь @Shumilov_AS | Раздел: Прикладная математика / Численные методы
Кратко. . .
|
|
сукцессия 40. Ансамблевая кластерная параметризаци, часть 1.
anaschu 24.07.2026
Пр# Сопровождение научной статьи ИИ-ассистентом: подготовка публикации и калибровка агентно-ориентированной модели сукцессии микоризных систем
**Полевые заметки о двухнедельной совместной работе**. . .
|
Теория всего 12. ВГК на планете в стратегической игре "терра"
anaschu 21.07.2026
### Главные семантические изменения и дешифровка новой физики
1. **`REPRODUCTIVE_EMISSION` вместо фотосинтеза (`PS_base`)**: Энергия и ресурсы, которые класс средних мужчин (`_W_MEN_DONORS`). . .
|
Публикация отклонённая на хабре. Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование задачи и целеполагание
Hrethgir 21.07.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11948&stc=1&d=1784657928
Привет Хабр. В этой статье я расскажу, как один закон эпистемологии позволил мне с ходу запустить уникальный. . .
|
Теория всего 11. Основные параметры
anaschu 21.07.2026
Дешифровка тензорного ядра Soil Chemistry 2. 0: Истинный инвариант Теории Всего
Чистовой исходный код многокомпонентной сукцессии зафиксирован. Модель оперирует единым вектором состояния. . .
|