Область видимости переменных в C++

Область видимости переменных в C++

Рассмотрим одну из основных задач, встречающихся в программах на C++. Пусть требуется вернуть объект из функции.

Проще всего сделать копию:

Это работает, но если объект большой, то мы теряем время на копирование. Лучше вернуть значение через указатель на объект:

Оператор new выделяет память, инициализирует объект и возвращает его адрес. Вот как можно использовать эту функцию:

Обратите внимание, что мы явно вызываем оператор delete, когда объект, на который указывает указатель, больше не нужен. После вызова объект разрушается, а память помечается, как незанятая.

РЕКОМЕНДУЕМ: Пять правил оптимизации программ

Если память не освобождать, то можно всю ее израсходовать. В этом случае новые объекты создать не получится. Но не бойтесь: после завершения работы приложения (возможно, аварийного) память в любом случае освобождается и попадает под управление операционной системы.

У вас мог возникнуть вопрос: «А зачем создавать объект с помощью new, если можно вернуть адрес объекта»? Примерно так:

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

Но ведь мы до этого спокойно вернули объект из func1(), почему же там все было в порядке? Причина в области видимости переменной.

Оператор new выделяет память для переменных в куче. Под кучей понимают общую в рамках процесса память. С ней ничего не случится, если только не освободить выделенную для переменной память с помощью delete.

Память для локальных переменных выделяется в стеке. Стек существенно меньше кучи, поэтому локальные переменные в нем надолго не задерживаются.

В большинстве случаев правило определения времени жизни и области видимости локальных переменных довольно простое: локальная переменная существует только внутри фигурных скобок:

То, что происходит при вызове func3(), равносильно следующему:

В случае же использования func1() все нормально (похоже, но не равносильно):

Выводы

Если требуется вернуть из функции переменную примитивного типа, то используйте обычное копирование (как в func1()). Объекты создавайте с помощью new и возвращайте через указатель (как в func2()).

Будьте осторожны при работе с указателями! Если указатель указывает на локальную переменную, которая уже вышла из области видимости, то он становится некорректным. Пользоваться им нельзя, но компилятор вам об этом не скажет.

РЕКОМЕНДУЕМ: Основные структуры данных в C++

Понравилась статья? Поделиться с друзьями:
Добавить комментарий