768 _____ ______Часть II. Программирование на C++

же верно, то для данных, на которые они указывают, это совершенно не так (разница между указателями и данными, на которые они указывают, чрезвычайно важна!).

Возврат адреса объекта. Чем дальше вы изучаете C++, тем чаще будете встречаться с функциями, возвращающими адрес некоторого объекта. Это означает, что в комбинации с типом возвращаемого аргумента используется операция получения адреса (&), вот так:

Return_Type &Function_Name( [Argument_List]);

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

Приведем простой пример подобной ошибки:

// Пример проблемы утечки. Возврат ссылки на локальный объект

//в лучшем случае даст неверный результат, а в худшем приведет

//к сбою программы.

int SReturnLocalInteger()

{

int val = 5;

return &val;

}

Результат выполнения этой функции не определен. Иногда это может сработать, но в действительности это типичный пример проблемы утечки памяти. Чтобы наглядно представить себе, что это за проблема, представьте себе указатель, указывающий на некий неопределенный блок памяти; причина возникновения подобной ситуации является частью проблемы утечки. Короче, утечка — это когда указатели сами по себе, а блоки памяти сами по себе.

Общее правило: не возвращайте ссылок на локальные объекты. Бывают ситуации, когда следует возвращать именно ссылки (мы будем обращать особое внимание на эти случаи, когда они будут возникать). Эти случаи мы будем изучать несколько позже.

Возврат указателя на локальный объект. В большинстве случаев использовать операцию разыменования (*) для возврата указателя на локальный блок памяти неверно. Представьте, например, что вы хотите разместить внутри функции массив целых чисел. В общем-то, неплохо бы уничтожить этот массив перед выходом из функции.

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