2

I have the following piece of code, which is an implementation of an array resizing function. It seems to be correct, but when I compile the program I get the following errors:

g++ -Wall -o "resizing_arrays" "resizing_arrays.cpp" (in directory: /home/aristofanis/Desktop/coursera-impl)
resizing_arrays.cpp: In function ‘int main()’:
resizing_arrays.cpp:37: error: invalid initialization of non-const reference of type ‘int*&’ from a temporary of type ‘int*’
resizing_arrays.cpp:7: error: in passing argument 1 of ‘void resize(int*&, int, int, int)’
resizing_arrays.cpp:39: error: invalid initialization of non-const reference of type ‘int*&’ from a temporary of type ‘int*’
resizing_arrays.cpp:7: error: in passing argument 1 of ‘void resize(int*&, int, int, int)’
resizing_arrays.cpp:41: error: invalid initialization of non-const reference of type ‘int*&’ from a temporary of type ‘int*’
resizing_arrays.cpp:7: error: in passing argument 1 of ‘void resize(int*&, int, int, int)’
Compilation failed.

Here is the code:

int N=5;

void resize( int *&arr, int N, int newCap, int initial=0 ) { // line 7
  N = newCap;
  int *tmp = new int[ newCap ];
  for( int i=0; i<N; ++i ) {
    tmp[ i ] = arr[ i ];
  }
  if( newCap > N ) {
    for( int i=N; i<newCap; ++i ) {
      tmp[ i ] = initial;
    }
  }

  arr = new int[ newCap ];

  for( int i=0; i<newCap; ++i ) {
    arr[ i ] = tmp[ i ];
  }
}

void print( int *arr, int N ) {
  for( int i=0; i<N; ++i ) {
    cout << arr[ i ];
    if( i != N-1 ) cout << " ";
  }
}

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

  print( arr, N );
  resize( arr, N, 5, 6 ); // line 37
  print( arr, N);
  resize( arr, N, 10, 1 ); // line 39
  print( arr, N );
  resize( arr, N, 3 ); // line 41
  print ( arr, N );

  return 0;
}

Could anyone help me? Thanks in advance.

Rontogiannis Aristofanis
  • 8,883
  • 8
  • 41
  • 58

5 Answers5

8

In main, you declare

int arr[] = { 1, 2, 3, 4, 5 };

an ordinary array, not an int*, which is what you would have to pass to resize.

And, although that is not technically necessary for your implementation of resize, since you never delete[] any allocated memory there - a space leak you should fix -, the pointer you pass to resize should point to a new-allocated memory block (that you should delete[] in resize).

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • it is impossible to resize a static array, so this isn't _quite_ the right advice, though you did identify the problem. – Mooing Duck Oct 02 '12 at 18:11
  • As is, passing any `int*` to `resize` will leak-but-work, `resize` will make it point to a different location (losing the possibly last reference to the old block). – Daniel Fischer Oct 02 '12 at 18:17
7

arr is an array that's allocated on the stack. You can't change its size. If you need a resizable array, use a pointer and allocate the array with new.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
1

An array is not a pointer. In particular, an array stays put. You cannot move it. In the context you are using the poibters you would also create memory leaks and out of bound accesses.

To create a resizable array, you will need to maintain a pointer which gets initially set up from a copy of the elements in you array. Personally, I wouldn't bother and use std::vector<int> (unless I'm working on my own standard C++ library and implement std::vector<T>).

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

The reason you're getting the specific error you're getting is that arr will decay to a temporary int* as used. You then try and bind a non-const reference (the parameter) to the temporary, which is illegal. See here:

How come a non-const reference cannot bind to a temporary object?

Community
  • 1
  • 1
Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80
0

When you say int& it means that an int variable that I can change its value, similarly when you say int*&, it means an int* variable that I can change its value. now look at your code can you change the value of arr. is it legal to say arr = new int[10]? you see it is not legal, in C++ term it is not an Lvalue(it can't sit in left side of equal operator) and all non-const references must be Lvalue

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
BigBoss
  • 6,904
  • 2
  • 23
  • 38
  • 1
    both `arr` and `new int[10]` can be on the right side of an equal operator, and all mutable references must be _lvalues_. – Mooing Duck Oct 02 '12 at 20:24
  • @MooingDuck thanks for your comment, it was a simple mistake!! I mean lvalue too. thanks again – BigBoss Oct 02 '12 at 20:29