stack - memory-management - стек куча swift - Что и где стопка и куча?

стек куча очередь / memory-management / language-agnostic / heap / dynamic-memory-allocation

Книги по языку программирования объясняют, что типы значений создаются в стеке , а ссылочные типы создаются в куче , без объяснения, что это за две вещи. Я не читал четкого объяснения этого. Я понимаю, что такое стек . Но,

RajeshKdev



Answer #1

Я предоставлю несколько простых аннотированных C-кодов,чтобы проиллюстрировать все это.Лучший способ научиться-это запустить программу под отладчиком и наблюдать за ее поведением.Если вы предпочитаете читать python,перейдите к концу ответа :)

// Статически размещается в сегменте данных при первой загрузке программы / DLL
// Освобождается при выходе из программы / DLL
// область видимости - можно получить доступ из любого места в коде
int someGlobalVariable;

// Статически размещается в сегменте данных при первой загрузке программы
// Освобождается при выходе из программы / DLL
// область видимости - можно получить доступ из любого места в этом конкретном файле кода
static int someStaticVariable;

// "someArgument" выделяется в стеке каждый раз, когда вызывается MyFunction
// "someArgument" освобождается, когда MyFunction возвращает
// область видимости - доступна только в MyFunction ()
void MyFunction(int someArgument) {

    // Статически размещается в сегменте данных при первой загрузке программы
    // Освобождается при выходе из программы / DLL
    // область видимости - доступна только в MyFunction ()
    static int someLocalStaticVariable;

    // Выделяется в стеке каждый раз при вызове MyFunction
    // Освобождается, когда MyFunction возвращает
    // область видимости - доступна только в MyFunction ()
    int someLocalVariable;

    // * указатель * выделяется в стеке каждый раз, когда вызывается MyFunction
    // Этот указатель освобождается, когда MyFunction возвращает
    // область видимости - к указателю можно получить доступ только внутри MyFunction ()
    int* someDynamicVariable;

    // В этой строке выделяется место для целого числа в куче
    // когда эта строка выполняется. Обратите внимание, это не в начале
    // вызов MyFunction (), как и автоматические переменные
    // область видимости - только код внутри MyFunction () может получить доступ к этому пространству
    // * через эту конкретную переменную *.
    // Однако, если вы передадите адрес в другое место, этот код
    // тоже можем получить к нему доступ
    someDynamicVariable = new int;


    // Эта строка освобождает место для целого числа в куче.
    // Если бы мы не писали это, память была бы «просочена».
    // Обратите внимание на фундаментальную разницу между стеком и кучей
    // кучей нужно управлять. Стек управляется за нас.
    delete someDynamicVariable;

    // В других случаях вместо освобождения этого пространства кучи вы
    // может сохранить адрес в более постоянном месте, чтобы использовать его позже.
    // Некоторые языки даже позаботятся об освобождении памяти ... но
    // всегда о нем нужно позаботиться во время выполнения каким-либо механизмом.

    // Когда функция возвращается, someArgument, someLocalVariable
    // и указатель someDynamicVariable освобождаются.
    // Пробел, на который указывает someDynamicVariable, уже был
    // освобождается перед возвратом.
    return;
}

// Обратите внимание, что someGlobalVariable, someStaticVariable и
// someLocalStaticVariable продолжает существовать, а не
// освобождается до выхода из программы.

Некоторые из вариантов синтаксиса в языке Си/Си++усугубляют эту проблему-например,многие люди считают,что глобальные переменные не являются "статическими" из-за синтаксиса,показанного ниже.

int var1; // Имеет глобальную область видимости и статическое размещение
static int var2; // Имеет область видимости файла и статическое размещение

int main() {return 0;}

Некоторые люди считают эти понятия специфическими для С/С++.Это не так.Например,приведенный ниже пример с Python иллюстрирует все три типа выделения (в интерпретируемых языках возможны некоторые тонкие различия,на которые я здесь не пойду).

from datetime import datetime

class Animal:
    _FavoriteFood = 'Undefined' # _FavoriteFood размещается статически

    def PetAnimal(self):
        curTime = datetime.time(datetime.now()) # curTime выделяется автоматически
        print("Thank you for petting me. But it's " + str(curTime) + ", you should feed me. My favorite food is " + self._FavoriteFood)

class Cat(Animal):
    _FavoriteFood = 'tuna' # Обратите внимание, поскольку мы переопределяем, класс Cat имеет свою собственную статически выделенную переменную _FavoriteFood, отличную от переменной Animal

class Dog(Animal):
    _FavoriteFood = 'steak' # Точно так же класс Dog получает собственную статическую переменную. Важно отметить, что эта статическая переменная является общей для всех экземпляров Dog, поэтому она не является динамической!


if __name__ == "__main__":
    whiskers = Cat() # Динамически распределяется
    fido = Dog() # Динамически распределяется
    rinTinTin = Dog() # Динамически распределяется

    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()

    Dog._FavoriteFood = 'milkbones'
    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()

# Вывод:
# Спасибо, что погладили меня. Но сейчас 13: 05: 02.255000, ты должен меня покормить. Моя любимая еда - тунец
# Спасибо, что погладили меня. Но сейчас 13: 05: 02.255000, ты должен меня покормить. Моя любимая еда - стейк
# Спасибо, что погладили меня. Но сейчас 13: 05: 02.255000, ты должен меня покормить. Моя любимая еда - стейк
# Спасибо, что погладили меня. Но сейчас 13: 05: 02.255000, ты должен меня покормить. Моя любимая еда - тунец
# Спасибо, что погладили меня. Но сейчас 13: 05: 02.255000, ты должен меня покормить. Моя любимая еда - молочные кости
# Спасибо, что погладили меня. Но сейчас 13: 05: 02.256000, ты должен меня покормить. Моя любимая еда - молочные кости