Почему мы не можем передать массив int [] в hoo (int * & p)? - PullRequest
0 голосов
/ 09 января 2019

В моем понимании array в int array[]={1,2,3,4,5} - это просто указатель на первый элемент array. Это означает, что array может быть назначен указателю ptr типа int*.

Параметр int* &p в hoo передаст аргумент по ссылке. Это означает, что мы можем изменить переданный аргумент так, чтобы он указывал на другое значение из hoo.

void hoo(int* &p, int n)
{
    for (int i = 0; i < n; i++)
        cout << p[i] << endl;
}

int main()
{
    int array[] = { 1,2,3,4,5 };

    // I can do this
    int* ptr = array;
    hoo(ptr, 5);

    // but not this.
    //hoo(array, 5);
}

Вопрос

Почему мы не можем передать int array в hoo без ptr?

Ответы [ 3 ]

0 голосов
/ 09 января 2019

Когда функция принимает параметр int* &, то есть (неподвижную) ссылку на указатель на int - тогда должна существовать истинная переменная-указатель, к которой относится эта ссылка ссылаясь. Это не может быть временное значение указателя. Таким образом, вы не можете сделать:

int x;
hoo(&x, 123);

потому что нет переменной-указателя для ссылки - только временная. По сути, то же самое с твоим int[5]. На самом деле нигде нет переменной int* - всего 5 int с. Когда вы передаете array в hoo(), то, что C ++ делает с этим идентификатором, это затухание массива в указатель : фактически оно пропускает &(array[0]). Так что, как и в предыдущем случае, это не скомпилируется.

0 голосов
/ 09 января 2019

Другие ответы уже объясняют проблему. Я хочу предложить изменить практику кодирования.

Использование void hoo(int* &p, int n) в качестве объявления функции очень старый стиль. Используя шаблоны, вы можете позволить компилятору определять размер и получать ссылку на массив, что устраняет необходимость использования указателя.

template <size_t N>
void hoo( int (&p)[N]) // The argument is a reference to an array of N elements.
{
    for (int i = 0; i < N; i++)
        cout << p[i] << endl;
}

Вызов функции становится естественным.

int array[] = { 1,2,3,4,5 };
hoo(array);

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

void hoo(int* p, size_t N)
{
    for (int i = 0; i < N; i++)
        cout << p[i] << endl;
}

template <size_t N>
void hoo( int (&p)[N]) // The argument is a reference to an array of N elements.
{
    hoo(p, N);
}
0 голосов
/ 09 января 2019

В моем понимании массив в массиве int [] = {1,2,3,4,5} - это просто указатель на первый элемент массива.

Это не правильно. Массивы - это массивы, а указатели - это указатели. Это разные типы с разными свойствами. Они часто путаются, потому что у массива есть свойство, что он будет стремительно распадаться на указатель на свой первый элемент.

hoo(array, 5); пытается преобразовать array в int*, но результатом этого преобразования является значение r, которое не может быть привязано к ссылке, отличной от const. Например, если вы изменили hoo, чтобы получить ссылку const, он скомпилируется нормально:

void hoo(int* const &p, int n) { }

int main()
{
    int array[] = { 1,2,3,4,5 };
    hoo(array, 5);
}

В этом случае вы не можете изменить на что указывает p, делая использование ссылки бессмысленным.

...