Когда будет уничтожен фрейм?

143
22 января 2020, 12:20

Читал я тему про перегрузку операторов и видел, что, собственно, из этого метода возвращается ссылка на новый объект, но ведь есть такая вещь - время жизни переменной, и её время жизни ограничено временем выполнения метода, и как только метод закончит свою работу, из стека будет выпилен фрейм стека вместе со всеми локальными переменными. И каким тогда образом переменная та вернётся?

Вот пример кода, чтобы хоть как-то конкретизировать:

class Counter
{
    public int Value { get; set; }
    public static Counter operator +(Counter c1, Counter c2)
    {
        return new Counter { Value = c1.Value + c2.Value };
    }
    public static bool operator >(Counter c1, Counter c2)
    {
        return c1.Value > c2.Value;
    }
    public static bool operator <(Counter c1, Counter c2)
    {
        return c1.Value < c2.Value;
    }
}

Теперь я бы хотел уточнить: когда, собственно, фрейм этого самого операторного метода будет "уничтожен", с момента когда мы вернём значение или же когда мы попадём на закрывающую скобку?

Answer 1

Ладно, попробую, если что - сильно не бить, давненько не приходилось поднимать подобные темы из памяти, что-то мог и забыть.

Для начала основной вопрос:

когда, собственно, фрейм этого самого операторного метода будет "уничтожен", с момента когда мы вернём значение или же когда мы попадём на закрывающую скобку?

Фигурные скобки (C, С++, C# и им подобные), begin-end и аналогичные конструкции других языков - это всего лишь условность, подсказка компилятору, где блок кода начинается и где заканчивается. Т.е. для исполняемого кода их не существует. Завершение работы метода происходит при выполнении команды return (в IL-коде ret, в ASM-е тоже есть аналогичная команда. Работать и интерпретироваться они, разумеется, могут и будут по-своему).

Стоит немного оговориться, что в режиме отладки иногда (в C# можно) действительно можно попасть как на открывающий, так и на закрывающий терм, однако это также условность, но уже отладчика. И хотя в некоторых случаях для реализации подобного поведения отладчика используют специальные "пустые" низкоуровневые операции, на которых можно остановиться во время выполнения без имитации, а по-настоящему, это фактически ничего не меняет - условность остается условностью.

Ну и попробую помочь немного выпутаться из "дебрей". Для начала несколько базовых понятий, которые нужно четко различать и, крайне желательно, использовать соответствующие термины по назначению.

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

Значение переменной - непосредственно данные. Данные могут храниться в переменной непосредственно (так называемые типы-значения) или в отдельном сегменте памяти - куче. В последнем случае в переменной будет храниться значение ссылки (или указателя, если говорить не только про C#), по которой к ним можно обратиться.

Большинство (могу ошибаться) современных ЯП используют, так называемую, стековую модель работы с памятью в исполняемом коде. Фактически это означает, что все локальные переменные в исполняемом коде размещаются на стэке. Передача параметров подпрограммам и возврат результата в такой модели также происходит через стэк. При этом команды исполняемого кода и данные, с которыми он работает, фактически, находятся в отдельных блоках памяти и не пересекаются.

Что происходит при вызове подпрограммы в стековой модели:

  1. Запоминается текущее положение вершины стека.
  2. На вершину кладутся входные параметры.
  3. Управление передается подпрограмме.
  4. Выполнение кода подпрограммы до одной из команд return.
  5. Восстановление сохраненного состояния вершины стека.
  6. Запись в стек результата (если необходимо)
  7. Возврат управления вызвавшему коду.

Практически сразу видно одно из главных преимуществ подобного подхода - простейшая очистка памяти, занимаемой локальными переменными, после завершения подпрограммы. Можно сказать очистка памяти выполняется одной командой процессора (см. пункт 5).

Данное описание, разумеется очень обобщенное. Реализации могут отличаться, но общая схема все равно сохраняется, так как имеет ряд преимуществ, которые перекрывают имеющиеся недостатки.

READ ALSO
Чтение из файла C#

Чтение из файла C#

Делал так:

128
Как прочитать данную php переменную?

Как прочитать данную php переменную?

Как прочитать данную php переменную?

132
как правильно передать в атрибут value код php?

как правильно передать в атрибут value код php?

Как правильно передать в атрибут value код php? Я знаю, что код неверно вложилаЕсли не передавать в переменную код работает

150