Почему не передаётся массив в функцию через указатель по ссылке (ссылочный указатель)?
Почему данная запись не работает?
#include <iostream>
using namespace std;
void foo(int *&pa){}
int main()
{
int a[4]{};
foo(a);
}
А когда я записываю так, то всё работает. В двух случаях же адрес указателя пытаюсь передать (значение указателя), т.е. сам указатель, в функцию, не создавая при этом новый, а просто ссылаясь на тот указатель. Имя массива может же служить указателем на его первый элемент, т.е. может хранить адрес первого элемента массива. Просто в первом случае я пропустил промежуточный указатель, т.к. имя массива тоже может служить им, но программа поломалась. Адрес то тот же передаю в функцию.
#include <iostream>
using namespace std;
void foo(int *&pa){}
int main()
{
int a[4]{};
int *x = a;
foo(x);
}
Кстати, если создать динамический массив int *a = new int[4]; и потом передать a в функцию, то это тоже будет работать, что логично и работает адекватно.
Интересует именно c++.
Ответы (2 шт):
В объявлении void foo(int *&pa){} функция foo() принимает в качестве параметра ссылку на указатель, т.е. на переменную в памяти, содержащую адрес массива. А в первом случае у вас нет этой переменной, вы пытаетесь передать непосредственный адрес массива, на который нельзя ссылаться по причине его физического отсутствия в памяти. По-этому и не работает.
Попытаюсь расширить объяснение: по ссылке в теле функции foo() вы можете изменить значение переданного указателя. Например:
#include <iostream>
using namespace std;
int b[5];
void foo(int *&pa)
{
pa = b; //изменяем указатель по ссылке
}
int main()
{
int a[4]{};
int* p = a;
//сейчас p содержит адрес a
foo(p);
//а сейчас p содержит адрес b
//а этот вызов не имеет смысла:
foo(a);
//...так как a - это непосредственный адрес массива a[], вы не можете его менять.
}
Как-то так.
P.S. И что тут кому не понравилось в моём объяснении??
При преобразовании массива в указатель на его первый элемент, указатель вычисляется на лету и не существует в памяти до преобразования.
Указатель, получающийся в результате преобразования - rvalue (prvalue, если точнее). Грубо говоря это временный объект (хотя формально prvalue - вообще не объекты).
А неконстантные lvalue-ссылки можно инициализировать только lvalue. Отсюда ошибка.