Распределение памяти для функций в C ++ - PullRequest
7 голосов
/ 04 августа 2010

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

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

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

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

Спасибо!

Ответы [ 4 ]

9 голосов
/ 04 августа 2010

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

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

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

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

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

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

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

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

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

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) и также уничтожить этот стек стека.

4 голосов
/ 04 августа 2010
  1. без разницы
  2. локальные переменные создаются и уничтожаются в стеке за вызов функции
2 голосов
/ 04 августа 2010
  1. Очень маловероятно, что будет разница

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

редактировать: слишком медленно:)

0 голосов
/ 04 августа 2010
  1. Разницы на самом деле не так уж много. Оба хранятся в памяти только один раз, когда вызывается нестатический метод, указатель на текущий объект (указатель this) помещается в стек (или сохраняется в ECX в зависимости от вашего компилятора) в дополнение ко всем функциям. параметры. Статическая функция не нуждается в экземпляре класса, поэтому она вызывается как обычная функция Си.

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

...