PLLUG C++/Qt Roadmap Book
  • Вступ
  • Найважливіший розділ у цій книжці
    • Кілька критично важливих порад
    • Встановлення середовища та початок роботи
    • Підготовка до роботи. Командний рядок.
      • Встановлення та налаштування суперконсолі (тільки на Windows)
      • Cheatsheet: Робота з командним рядком
    • Компіляція та запуск першої програми
      • Найменьша програма мовою С++
      • Компіляція програми: як це працює
      • Починаємо програмувати
    • Базова робота з Git та створення власного репозиторію
      • Підготовка до роботи
      • Створюємо репозиторій та заливаємо на GitHub
      • Cheatsheet: Простий алгоритм для роботи з системою контролю версій (одна гілка, один розробник)
      • Працюємо з Git правильно
  • Мова С++ - швидкий вступ та обрані теми
    • Змінні. Деякі з основних типів та їх застосування.
      • Типи int та double
      • Тип bool
      • Тип char
      • Тип std::string
      • Тип std::vector
      • Тип std::array
    • Ключове слово const
  • Середовище розробки QtCreator
    • Налаштування та підготовка до роботи
      • Налаштування інструментаріїв
    • Довідка та ресурси
    • Гарячі клавіші
    • Робота з проектами у QtCreator
      • Файли проекту
      • Основні змінні, які беруть участь у описі проекту
      • Компіляція проекту Qt
      • Очистка проекту
  • Абстрактні типи даних та керування памяттю
    • Абстрактні типи даних
      • Об'єкти та класи. Абстракція.
      • Поля та методи класу
      • Успадкування
      • Віртуальні методи та поліморфізм
    • Вказівники та пам'ять
      • Адреса
      • Вказівники
      • Вказівники: примітивна демонстрація програми у пам'яті
      • Час зберігання об'єкту
  • Знайомство з Qt5
    • Огляд Qt5
      • Ласкаво просимо у світ Qt
      • Огляд можливостей Qt 5
      • Ліцензування Qt
      • Короткий огляд історії Qt
      • “Екосистема” Qt
    • Створення графічного інтерфейсу засобами Qt
      • Віджети (Widgets)
      • Компонування (Layouts)
      • Сигнально-слотові з'єднання
      • Створення сигналів (signals) та слотів (slots)
      • Підсумок: сигнально-слотові з'єднання
      • Коротко про елементи графічного інтерфейсу та їх використання
  • Cheatsheets
  • Demos
  • Missions
    • Mission 1: Досліджуємо Git та командний рядок
    • Mission 2: Консольна гра
    • Mission 3: MazeGame
    • Mission 4: Створюємо абстрактний тип даних
Powered by GitBook
On this page
  • Автоматичний час зберігання
  • Статичний час зберігання
  1. Абстрактні типи даних та керування памяттю
  2. Вказівники та пам'ять

Час зберігання об'єкту

PreviousВказівники: примітивна демонстрація програми у пам'ятіNextЗнайомство з Qt5

Last updated 6 years ago

Для того, щоб мати можливість оперувати даними у програмі, ми оголошуємо змінні та створюємо об'єкти. Дані, які містять змінні та об'єкти, знаходяться у пам'яті. Для спрощення та відповідності зі стандартом мови, називатимемо і змінні простих вбудованих типів і екземпляри класів просто об'єктами ().

Коли ми створюємо об'єкт у програмі - ми вказуємо, що необхідно виділити пам'ять для збереження даних, які містить цей об'єкт. У деякий момент, ця пам'ять буде вивільнена (наприклад, якщо програма завершила виконання). Час протягом якого, ці данні будуть доступні, поки пам'ять яка їх містить не буде вивільнена для інших потреб, ми називатимемо часом життя об'єкту ().

Час життя пов'язаний з тривалістю зберігання () об'єкту. Ми познайомимося з двома видами часу зберігання: автоматичний та статичний.

Автоматичний час зберігання

Звичайні локальні об'єкти, які ми оголошуємо всередині деякого блоку коду, існують лише в межах цього блоку. Тому, коли виконання програми вийде за межі блоку коду, пам'ять автоматично вивільниться.

Покажемо це на прикладі. Для наочної демонстарції, створимо простий клас:

class MyClass
{
public:
    MyClass() { std::cout << "Object created!" << std::endl; }
    ~MyClass() { std::cout << "Object destroyed!" << std::endl; }
};

Цей клас має два спеціальні методи: конструктор MyClass() та деструктор ~MyClass(). Нагалаємо, що для будь якого класу конструктор завжди автоматично викликається, коли створюється новий об'єкт класу. А деструктор, завжди автоматично викликається коли об'єкт класу знищується.

Тепер напишемо дуже просту програму:

int main()
{
    std::cout << "Program begin!" << std::endl;

    {
        MyClass obj;
    }

    std::cout << "Program end!" << std::endl;
}

Тут об'єкт obj створено всередині окремого блоку коду. Після запуску програми ми побачимо вивід у консоль:

Program begin!
Object created!
Object destroyed!
Program end!

Тобто, як тільки виконання блоку коду завершилось - одразу ж викликався деструктор об'єкту і його було видалено з пам'яті.

Автоматичний час зберігання мають також об'єкти оголошені всередині функцій, блоків if, циклів, тощо. Тому ніколи не можна використовувати посилання чи вказівник на автоматичний об'єкт поза межами блоку, в якому він існує. Наприклад, якщо ми маємо функцію яка повертає посилання чи вказівник на локальну змінну всередині функції (чого не можна робити!) і ми скористаємося цим вказівником\посиланням, то у кращому випадку програма аварійно завершиться, а у гіршому - буде працювати некоректно (і як часто буває в таких випадках - дуже дивно).

Ткож варто пам'ятати, що у випадку примітивних типів такіх як int, float, bool, вказівників тощо, автоматичні змінні завжди необхідно ініціалізовувати початковим значенням. Вони не ініціазізуються за замовчуванням автоматично, і якщо їх не ініціалізувати - вони міститимуть довільне значення (по суті, сміття з пам'яті).

void someFunc()
{
    int value1 = 0; // Коректно - ініціалізовано значенням 0
    int value2;     // Не правильно! Необхідно ініціалізувати! Містить "сміття" з пам'яті.
}

Статичний час зберігання

Глобальні об'єкти, а також об'єкти, які оголошені зі специфікатором static існують до завершення роботи програми.

Розглянемо приклад:

MyClass obj;

int main()
{
    std::cout << "Program begin!" << std::endl;
    std::cout << "Program end!" << std::endl;
}

Консольний вивід виглядатиме так:

Object created!
Program begin!
Program end!
Object destroyed!

Як ми бачимо з прикладу, об'єкт оголошений глобально був створений ше до початку виконання main(), а видалений вже після закінчення роботи програми.

У випадку статично змінної (наприклад оголошеної всередині функції):

MyClass obj;

void func()
{
    static MyClass obj;
}

int main()
{
    std::cout << "Program begin!" << std::endl;
    func();
    func();
    std::cout << "Program end!" << std::endl;
}

Вивід виглядатиме так:

Program begin!
Object created!
Program end!
Object destroyed!

На прикладі цієї програми ми бачимо, що статичний об'єкт було створено при першому виклику функції func(), а знищено вже після роботи програми. Зверніть увагу: навіть при другому виклику функції func() повторного створення об'єкту не відбулося.

Статичні об'єкти (оголошені як static) створюються лише один раз за час роботи програми і існують до кінця її роботи. Наприклад, якщо ми оголосимо змінну типу int у функції та присвоїмо їй якесь значення, то при наступному виклику ця змінна матиме те ж саме значення, яке ми їй присвоїли.

object
object lifetime
storage duration