Выделение памяти для переменной внутри функции и передача уже выделенной памяти в функцию

75
01 мая 2021, 00:00

1 вариант:

void func(int ** &arr, int size) {
    arr = new int * [size];
    <...>
}
int main() {
    int size = <...>;
    int **arr;
    func(arr, size);
}

2 вариант:

void func(int **arr, int size) {
   <...>
}
int main() {
    int size = <...>;
    int **arr = new int * [size];
    func(arr, size);
}

Объясните, пожалуйста, почему в первом варианте мы в функции выделяем память под массив и передаем arr по ссылке, а во втором варианте в main выделяем память и тогда уже не надо по ссылке в функцию передавать arr. Не понимаю, как тут работают указатели.

Answer 1

В первом случае мы объявляем переменную arr типа int **. Передаем ссылку на нее в функцию func и уже там присваиваем ей значение.

Во втором случае мы объявляем переменную arr типа int ** и сразу присваиваем ей значение — указатель на выделенную память.

Таким и образом, и первый и второй вариант код верный. Какой именно способ использовать зависит от ваших предпочтений и, собственно, решаемой этим кодом задачи.

…и тогда уже не надо по ссылке в функцию передавать arr

В первом случае мы могли бы воспользоваться указателем, а не ссылкой:

void func(int ***arr, size_t size) {
    *arr = new int * [size];
    <...>
}

Однако никто не мешает вам и во втором случае передавать arr по ссылке.

Answer 2

Никто не мешает в первом случае тоже выделять память в main. Но вот во втором случае выделять память в func не получится.

Смотрите, совсем простой пример:

#include <iostream>
void foo(int x)
{
    x = 1;
}
int main()
{
    int y = 0;
    foo(y);
    std::cout << y << '\n';
}

Что напечатает этот код, 1? Нет, 0, потому что x и y - разные переменные. А если сделать void foo(int &x), тогда результат будет 1.

С указателями то же самое.

Если вы внутри void func(int **arr, int size) сделаете arr = new ..., то переменная int **arr в main не изменится, и из main вы никак не получите доступ к этой памяти.

Однако! Если вы меняете arr[i] или *arr, то эти изменения в любом случае будут видны снаружи функции. При передаче arr из main в void func(int **arr, int size), копируется только сам указатель, но не то, на что он указывает (т.е. копируется адрес, записанный в указателе). То есть изменения самого указателя не будут заметны снаружи функции, в отличие от изменений того, на что он указывает.

READ ALSO
Ключевое слово this с++

Ключевое слово this с++

Возник такой вопросВ коде реализуется конструктор копирования обьекта

120
Как подключить библиотеку sfeMovie?

Как подключить библиотеку sfeMovie?

Я хочу подключить библиотеку sfeMovie (для отображения видео) к проектуДелаю всё по инструкции: http://sfemovie

108
Наследование абстрактного класса

Наследование абстрактного класса

У меня есть некий абстрактный класс, назовем его AbstrУ него есть чисто виртуальная функция, что выводит на экран принятый указатель (разыменовывает...

103
JQuery и одинаковые имена

JQuery и одинаковые имена

У меня есть 6 штук блоков, каждые называются одинаково, только значения в теге <b>12</b> разные

122