3
#include <iostream>

using namespace std;

void merge(int *& toMerge, int lo, int mid, int hi)
{
    int merged[hi+1];
    int i = lo, j = mid+1;
    for (int k = lo; k <= hi; k++)
    {
        if (i > mid) {merged[k] = toMerge[j]; j++;}
        else if (j > hi) {merged[k] = toMerge[i]; i++;}
        else if (toMerge[j] < toMerge[i]) {merged[k] = toMerge[j]; j++;}
        else {merged[k] = toMerge[i]; i++;}
    }
    toMerge = merged;
}

int main(int argc, const char * argv[])
{

    int x[8] = {1,7,4,6,2,7,3,2};
    merge(x, 0, 7, 3);
    return 0;
}

I am trying to pass a pointer by reference here such that the end result will be that the array x will be sorted. However, my compiler is throwing an error that there is no matching function call for the merge(x, 0, 7, 3).

I am not sure as to why this is happening because the merge function requires a pointer, and x is a pointer to the first element in the array -- so it should work. Why doesn't it?

1110101001
  • 4,662
  • 7
  • 26
  • 48
  • 1
    `x` is an array, not a pointer. – chris Jun 05 '14 at 23:42
  • Shouldn't `merge(&x[0], 0, 7, 3);` also work? – Cyclonecode Jun 05 '14 at 23:44
  • @KristerAndersson I already tried that -- didn't work – 1110101001 Jun 05 '14 at 23:46
  • @chris But doesn't `x` give you a pointer to the first element? – 1110101001 Jun 05 '14 at 23:47
  • 2
    @user2612743, `x` *decays* into a pointer to the first element. See [arrays](http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c). While I'm talking, I should point out that `int merged[hi+1];` is invalid because the size is not a compile time constant. – chris Jun 05 '14 at 23:53
  • How would I pass it as a reference to a pointer? Doing &x[0] doesn't work? And if I'm not mistaken C++11 added support for declaring those types of arrays. – 1110101001 Jun 05 '14 at 23:54
  • 1
    @user2612743, You need a pointer in `main` that is an lvalue (like a separate variable). Or you can change it to use `std::vector` (since the function won't work properly with `std::array` without some changes). Anyway, `&x[0]` is not an lvalue. It's a nameless temporary, which can't bind to a reference (it gets destroyed at the end of the function call anyway, so there's no point). And C++11 did not. Not even C++14. Compile with `-pedantic`. – chris Jun 05 '14 at 23:56

2 Answers2

4

An array decays to a pointer when you pass it as an argument to a function call but not to a reference to a pointer.

Imagine this:

void foo(int*& p)
{
   p = new int;
}

int main()
{
   int arr[6] = {0};

    foo(arr);
   // You don't want arr to be an invalid object here.
   // If the compiler allowed you to do that, that's what will happen.
   // Not only that, foo(arr); is equivalent to:
   // arr = new int;
   // which is not allowed in the language.
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

You really should NOT pass a reference, because you don't really want merge changing the value of the pointer. You just want to allow it to change the values stored in the array, which it can do without the reference (i.e., just from the pointer).

Dwayne Towell
  • 8,154
  • 4
  • 36
  • 49
  • Except I need an auxiliary array for mergesort and copying the elements back takes addition O(n) time. – 1110101001 Jun 05 '14 at 23:48
  • Huh? The array values are not copied when passing either a pointer, or a pointer to reference, or a reference to a pointer, or a reference. – Dwayne Towell Jun 05 '14 at 23:50
  • No, `merge()` has a syntactically correct signature. `T*&` is a reference to a pointer, not a pointer to a reference. – David G Jun 05 '14 at 23:51
  • I know -- if I were to just use a pointer and change the values stored in the array, I would have to update each value in the array with the sorted values, taking O(n) time. – 1110101001 Jun 05 '14 at 23:51
  • Another issue is that int merged[hi+1]; has local scope and you try to return it via a pointer. That pointer will then point to deallocated memory. – Xavier Leclercq Jun 05 '14 at 23:53
  • @XavierLeclercq True -- how does C++'s sort() handle this? – 1110101001 Jun 05 '14 at 23:56
  • @0x499602D2, well, silly me. Thanks. Not sure where my head was. – Dwayne Towell Jun 05 '14 at 23:58
  • @user2612743, It sorts in place. And there's no sort that takes O(n) time in general, so something being O(n) isn't really anything to worry about. – chris Jun 05 '14 at 23:59