Что означает, когда объект выходит из области видимости (scope) в C++?

«Что означает, когда объект выходит из области видимости (scope) в C++?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В C++ выход объекта из области видимости (scope) — это момент, когда исполнение программы покидает блок кода (обозначенный фигурными скобками {}), в котором этот объект был объявлен. Для автоматических (стековых) объектов это приводит к их автоматическому уничтожению: вызывается деструктор класса, и память, занимаемая объектом на стеке, освобождается.

Ключевые моменты:

  • Автоматическое управление памятью для стековых объектов. Не нужно вызывать delete или free.
  • Гарантированный вызов деструктора. Это основа идиомы RAII (Resource Acquisition Is Initialization), которая обеспечивает безопасное управление ресурсами (памятью, файлами, мьютексами).

Пример:

#include <iostream>
#include <string>

class Logger {
public:
    Logger(const std::string& name) : name_(name) {
        std::cout << "[" << name_ << "] Constructor.n";
    }
    ~Logger() {
        std::cout << "[" << name_ << "] Destructor.n";
    }
private:
    std::string name_;
};

void foo() {
    Logger outer("outer"); // Объект 'outer' входит в область видимости функции foo.
    {
        Logger inner("inner"); // Объект 'inner' входит в область видимости вложенного блока.
        std::cout << "Inside inner block.n";
    } // Конец вложенного блока. 'inner' ВЫХОДИТ из области видимости, вызывается ~Logger().
    std::cout << "Back in foo.n";
} // Конец функции. 'outer' ВЫХОДИТ из области видимости, вызывается ~Logger().

int main() {
    foo();
    return 0;
}

Вывод программы:

[outer] Constructor.
[inner] Constructor.
Inside inner block.
[inner] Destructor.
Back in foo.
[outer] Destructor.

Важное отличие от указателей: Если вы выделяете память в куче с помощью new, указатель на эту память может быть стековой переменной. Когда указатель выходит из области видимости, уничтожается только сам указатель (4 или 8 байт), но не память, на которую он указывает. Это приводит к утечке памяти. Решение — использовать умные указатели (std::unique_ptr, std::shared_ptr), которые являются RAII-обёртками: когда умный указатель выходит из области видимости, в его деструкторе вызывается delete для управляемого объекта.