Выделение памяти к функциям в C++

Я - все еще новичок C++. Просто прибыл, чтобы считать, что статическая функция членства класса не является конкретным объектом - существует единственная копия функций членства для всех объектов.

Теперь два вопроса возникают в моем уме:

  1. Каково различие между обычной функцией и статической функцией "с точки зрения выделения памяти только"?

  2. Что, если функция членства содержит некоторые локальные переменные? В этом случае функция "должна" иметь отдельную копию той переменной - характерный для объекта, вызывающего функцию... Как эта проблема решена в C++?

Спасибо!

7
задан Mark Ingram 4 August 2010 в 08:22
поделиться

4 ответа

В чем разница между обычная функция и статическая функция "с точки зрения памяти только выделение "?

Ничего. Статическая функция похожа на глобальную функцию, за исключением области видимости.

Даже для нестатических функций-членов дополнительная память не требуется. Функция-член int C :: f (int arg1, int arg2) - это просто синтаксический сахар для чего-то вроде int C__f (C * this, int arg1, int arg2) .

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

Есть копия локальных переменных для каждого вызова функции (если они не статические ). Вот почему в C ++ возможна рекурсия.

Как эта проблема решена в C ++?

Вызов функций основан на «кадрах стека». Кадр стека состоит из:

  • аргументов функции (включая неявное this , если применимо).
  • Любые другие не статические локальные переменные в функции.
  • «Адрес возврата», который сообщает процессору, где возобновить выполнение после выполнения функции.

Каждый раз, когда вызывается функция, создается кадр стека. Когда функция есть, фрейм стека уничтожается. Если функция вызывается рекурсивно, каждый уровень рекурсии получает свой собственный кадр стека. Например, если у вас есть

int factorial(int n) {
    if (n <= 1)
        return 1;
    else
        return factorial(n - 1) * n;
}

, то при вызове factorial (3) фрейм стека создается следующим образом:

------------------------ stack pointer (SP)
n = 3
RA = <in main()>

Когда выполняется рекурсивный вызов factorial (2) , в верхнюю часть стека добавляется дополнительный кадр

------------------------ SP
n = 2
RA = <in factorial()>
------------------------
n = 3
RA = <in main()>

Выполняется другой рекурсивный вызов factorial (1) .

------------------------ SP
n = 1
RA = <in factorial()>
------------------------
n = 2
RA = <in factorial()>
------------------------
n = 3
RA = <in main()>

Это базовый случай для рекурсии, и возвращаемое значение 1 сохраняется в регистре. После завершения вызова функции верхний фрейм стека уничтожается, и выполнение продолжается с сохраненным адресом возврата.

------------------------ SP
n = 2                                      
RA = <in factorial()>
------------------------
n = 3
RA = <in main()>

Теперь вызов factorial (2) может вычислить его возвращаемое значение (2), а другой кадр стека может быть уничтожен:

------------------------ SP
n = 3
RA = <in main()>

Наконец, мы можем вычислить результат исходного вызова функции (6), а также уничтожить этот фрейм стека.

9
ответ дан 6 December 2019 в 14:00
поделиться
  1. без разницы
  2. локальные переменные создаются и уничтожаются в стеке при вызове функции
4
ответ дан 6 December 2019 в 14:00
поделиться
  1. Я бы счел очень маловероятным, чтобы была разница

  2. Похоже, вам стоит немного почитать о разнице между кучей и выделением стека. Это дает хорошее представление о том, как работает память на низком, но все же высоком уровне. Извините, что не могу быть более полезным сейчас.

edit: too slow :)

2
ответ дан 6 December 2019 в 14:00
поделиться
  1. На самом деле нет такой большой разницы. Оба хранятся в памяти только один раз, когда вызывается нестатический метод, указатель на текущий объект (указатель this) помещается в стек (или сохраняется в ECX в зависимости от вашего компилятора) в дополнение ко всем функциям параметры. Статической функции не нужен экземпляр класса, поэтому она просто вызывается как обычная функция C.

  2. То же, что и в C, со стеком вызовов.

0
ответ дан 6 December 2019 в 14:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: