Возвращение указателей и ссылок

Последнее обновление: 06.03.2023

Возвращение указателя

При возвращении указателя из функции он должен содержать либо значение nullptr, либо адрес, который все еще действителен. Поэтому не следует возвращать из функции адрес автоматической локальной переменной, так как она удаляется после завершения этой функции. Так, рассмотрим следующий некорректный пример функции, которая возвращает большее число из двух:

// пример некорректного возвращения значения
int* max(int a, int b)
{
    if (a > b)
        return &a;
    else
        return &b;
}

Параметры функции аналогичны переменным - при вызове функции в стеке для них выделяется память. И вданном случае возвращается адрес участка памяти соответствующего параметра (return &a или return &b). Но после возвращения адреса функция завершает свою работу, соответствующие участки памяти очищаются, параметры удаляются, поэтому возвращенный адрес будет недействительным. И хотя компилятор даже может скомпилировать данную функцию, ограничившись предупреждениями, но такая функция не будет работать корректно.

Тем не менее это не значит, что мы в принципе не можем возвращать указатель из функции. Например, возьмем следующую ситуацию:

#include <iostream>

int* max(int*, int*);

int main()
{
    int n{5};
    int m{4};
    int* ptr = max(&n, &m);
    std::cout << "max: " << *ptr << std::endl; // max: 5
}
// пример корректного возвращения значения
int* max(int *a, int *b)
{
    if (*a > *b)    // разыменовываем указатели
        return a;
    else
        return b;
}

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

При этом нам необязательно присваивать результат переменной или константе, можно напрямую обратиться к результату функции:

int main()
{
    int n{5};
    int m{4};
    std::cout << "max: " << *max(&n, &m) << std::endl; // max: 5
}

Возвращение ссылки

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

// пример некорректного возвращения ссылки
int& max(int a, int b)
{
    if (a > b) 
        return a;
    else
        return b;
}

Здесь функция возвращает ссылку на максимальное значение - один из переданных параметров. Но поскольку память, выделенная для параметров, передаваемых по значению, после выполнения функции очищается, то возвращенная ссылка в итоге будет указывать на несуществующий объект.

Чтобы выйти из ситуации, мы можем передавать значения по ссылке:

#include <iostream>

int& max(int&, int&);

int main()
{
    int n{5};
    int m{4};
    int result = max(n, m);
    std::cout << "max: " << result << std::endl; // max: 5
}
// пример корректного возвращения ссылки
int& max(int& a, int& b)
{
    if (a > b) 
        return a;
    else
        return b;
}

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

#include <iostream>

const int& max(const int&, const int&);

int main()
{
    int n{5};
    int m{4};
    int result = max(n, m);
    std::cout << "max: " << result << std::endl; // max: 5
}
// пример корректного возвращения ссылки
const int& max(const int& a, const int& b)
{
    if (a > b) 
        return a;
    else
        return b;
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850