-2

In my understanding array in int array[]={1,2,3,4,5} is just a pointer to the first element of array. It means that array can be assigned to a pointer ptr of type int*.

Parameter int* &p in hoo will pass the argument by reference. It means we can change the passed argument to point to another value from within the 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);
}

Question

Why can't we pass int array to hoo without ptr ?

einpoklum
  • 118,144
  • 57
  • 340
  • 684
Second Person Shooter
  • 14,188
  • 21
  • 90
  • 165
  • *"Parameter `int* &p` in `hoo` will pass the argument by reference. It means we can change the passed argument to point to another value from within the `hoo`."* What if you tried to do `p=nullptr` in `hoo`? What would the intended result be for `array`? – François Andrieux Jan 09 '19 at 19:35
  • 2
    An array is __not__ a pointer to its first element. Your title asks a entirely different question than your question-text. You _can_ pass a `int[]` to a `int*`, but not to a `int*&`. – tkausl Jan 09 '19 at 19:35
  • @tkausl I edited the question title and it invalidates part of your comment. – François Andrieux Jan 09 '19 at 19:37
  • 2
    An array is **not** a pointer, full stop. It will save you many headaches if you treat an array as what it really is. Yes, it can decay to a pointer in most cases but don't think of it as a pointer. Additionally, you can just stop using raw arrays and use `std:array` in their place. They'll make issues like this go away. – NathanOliver Jan 09 '19 at 19:40
  • is there some real problem you are trying to solve or is this just for learning purpose? In either case, use an `std::array` or `std::vector` – 463035818_is_not_an_ai Jan 09 '19 at 19:41
  • @user463035818: learning c++ and opencv. – Second Person Shooter Jan 09 '19 at 19:44

3 Answers3

7

In my understanding array in int array[]={1,2,3,4,5} is just a pointer to the first element of array.

This is not correct. Arrays are arrays and pointers are pointers. They are distinct types with distinct properties. They are often confused because an array has the property that it will eagerly decay to a pointer to its first element.

hoo(array, 5); tries to convert array to an int* but the result of that conversion is an rvalue and can't be bound to a non-const reference. If, for example, you changed hoo to take a const reference it will compile fine :

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

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

In that case, you cannot change what p points to, making the use of a reference pointless.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
François Andrieux
  • 28,148
  • 6
  • 56
  • 87
3

When a function takes an int* & parameter, that is, a (non-move) reference to a pointer-to-an-int - then there needs to be a bona fide pointer variable to which that reference is referring. It can't be a temporary pointer value. Thus you can't do:

int x;
hoo(&x, 123);

because there's no pointer variable to refer to - just the temporary. It's essentially the same thing with your int[5]. There isn't actually an int* variable anywhere - there are just 5 ints. When you pass array to hoo(), what C++ does with that identifier is an array-to-pointer decay: It actually passes &(array[0]). So just like in the previous case, that won't compile.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
3

The other answers already explain the problem. I want to suggest a change of coding practice.

Use of void hoo(int* &p, int n) as function declaration is very very old style. Using templates, you can let the compiler deduce the size and get a reference to the array, which obviates the need for using a pointer.

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;
}

The call to the function becomes natural.

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

If your function needs to be able to support dynamically allocated arrays as well, you can overload the function as follows.

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);
}
Second Person Shooter
  • 14,188
  • 21
  • 90
  • 165
R Sahu
  • 204,454
  • 14
  • 159
  • 270