Хорошо, я понимаю, что такое стек и куча (значения живут в стеке, ссылки в куче
Я не думаю, что вы понимаете стек и кучу. Если значения находятся в стеке, то где же находится массив целых чисел? Целые числа - это значения. Вы говорите мне, что массив целых чисел хранит свои целые числа в стеке? Когда вы возвращаете массив целых чисел из метода, скажем, с десятью тысячами целых чисел в нем, вы говорите мне, что эти десять тысяч целых чисел копируются в стек?
Значения живут в стеке, когда они живут в стеке, и живут в куче, когда они живут в куче. Мысль о том, что тип объекта имеет отношение к сроку хранения, - нонсенс. Места хранения, которые недолговечны, помещаются в стек; места хранения, которые являются долгоживущими, помещаются в кучу, независимо от их типа. Долгоживущий int должен находиться в куче, как и долгоживущий экземпляр класса.
Когда я объявляю новый экземпляр класса, он сохраняется в куче со ссылкой на эту точку в памяти в стеке.
Почему ссылка должна идти в стек? Опять же, время жизни хранилища ссылки не имеет ничего общего с ее типом. Если хранилище ссылки является долгоживущим, то ссылка помещается в динамическую память.
Я также знаю, что C # выполняет собственную сборку мусора (т. Е. Определяет, когда созданный экземпляр класса больше не используется, и освобождает память).
В языке C # этого не происходит; CLR делает это.
Правильно ли я понимаю сборку мусора?
Кажется, вы верите в ложь о стеке и куче, так что шансы хорошие, нет, это не так.
Могу я сделать свое?
Не в C #, нет.
Я спрашиваю, потому что у меня есть метод в цикле For. Каждый раз, когда я прохожу цикл, я создаю новый экземпляр своего класса. В своей голове я представляю себе, как все эти классы лежат в куче, ничего не делают, кроме занимают память, и я хочу избавиться от них как можно быстрее, чтобы все было в порядке!
Весь смысл сборки мусора - избавить вас от забот о наведении порядка. Вот почему это называется «автоматический сбор мусора». Это прибирает для вас.
Если вас беспокоит, что ваши циклы создают давление сбора, и вы хотите избежать давления сбора по соображениям производительности, я советую вам придерживаться стратегии объединения. Было бы разумно начать с явной стратегии объединения; это:
while(whatever)
{
Frob f = FrobPool.FetchFromPool();
f.Blah();
FrobPool.ReturnToPool(f);
}
вместо того, чтобы пытаться выполнить автоматическое объединение с помощью восстанавливающего финализатора. Я не рекомендую использовать как финализаторы, так и воскрешение объекта в целом, если вы не являетесь экспертом в семантике финализации.
Пул, конечно, выделяет нового Frob, если его нет в пуле. Если он есть в пуле, он выдает его и удаляет из пула, пока он не будет вставлен обратно. (Если вы забудете вернуть Frob обратно в пул, GC в конце концов доберется до него.) Преследуя Стратегия объединения вы заставляете сборщик мусора в конечном итоге перемещать все Frobs в кучу поколения 2 вместо того, чтобы создавать большое давление сбора в куче поколения 0. Затем давление сбора исчезает, потому что новые Frobs не выделяются. Если что-то еще создает давление сбора, все Фробы благополучно находятся в куче 2-го поколения, где их редко посещают.
Это, конечно, полная противоположность описанной вами стратегии; весь смысл стратегии объединения состоит в том, чтобы заставить объекты висеть вечно. Предметы, вечно висящие рядом, - это хорошо, если вы собираетесь их использовать.
Конечно, не вносите такого рода изменения, пока через профилирование не узнаете, что у вас проблемы с производительностью из-за давления сбора! В настольной среде CLR такая проблема возникает редко; он чаще встречается в компактной среде CLR.
В более общем плане, если вы относитесь к тем людям, которым неудобно, когда диспетчер памяти очищает за вас по своему расписанию, то C # - неподходящий язык для вас. Вместо этого рассмотрим C.
person
Eric Lippert
schedule
04.01.2012