2

I am sort of new to C++. I am used to programming in Java. This particular problem is causing me great issues, because C++ is not acting like Java when it is dealing with Arrays. In C++, arrays are just pointers.

But why does this code:

#include <iostream>
#define SIZE 3
using namespace std;

void printArray(int*, int);
int * getArray();
int ctr = 0;

int main() {
  int * array = getArray();

  cout << endl << "Verifying 2" << endl;
  for (ctr = 0; ctr < SIZE; ctr++)
    cout << array[ctr] << endl;

  printArray(array, SIZE);
  return 0;
}

int * getArray() {
  int a[] = {1, 2, 3};
  cout << endl << "Verifying 1" << endl;
  for (ctr = 0; ctr < SIZE; ctr++)
    cout << a[ctr] << endl;
  return a;
}

void printArray(int array[], int sizer) {
  cout << endl << "Verifying 3" << endl;
  int ctr = 0;
  for (ctr = 0; ctr < sizer; ctr++) {
    cout << array[ctr] << endl;
  }
}

print out arbitrary values for verify 2 and verify 3. Perhaps this has something to do with the way arrays are really handled as pointers.

charmoniumQ
  • 5,214
  • 5
  • 33
  • 51
  • 3
    Arrays are not pointers. Anyway, if you want something like Java, use a container such as `std::array`. – chris Oct 05 '12 at 02:40
  • As for random printings, one thing I see is this: http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope – chris Oct 05 '12 at 02:42
  • 2
    What you're returning is a pointer, not an array. Worse, it's a pointer to memory that ceased to exist as `getArray` returned, so attempting to use the return value causes undefined behavior. – Jerry Coffin Oct 05 '12 at 02:42
  • Go through this article , cleared my confusion about array vs pointers....http://c-faq.com/aryptr/aryptr2.html – Mudassir Hasan Oct 05 '12 at 02:44

3 Answers3

9

The problem is that you cannot return local arrays:

int a[] = {1, 2, 3};
...
return a;

is invalid. You need to copy a into dynamic memory before returning it. Currently, since a is allocated in the automatic storage, the memory for your array gets reclaimed as soon as the function returns, rendering the returned value invalid. Java does not have the same issue because all objects, including arrays, are allocated in the dynamic storage.

Better yet, you should avoid using arrays in favor of C++ classes that are designed to replace them. In this case, using a std::vector<int> would be a better choice.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • I thought C++ has no trash collection? Or is this more of a scope/lifetime issue? – charmoniumQ Oct 05 '12 at 02:52
  • It's not regular garbage collection. It's the fact that when a method returns, that space in the stack contains unspecified content and will change when another function is called. – Corey Ogburn Oct 05 '12 at 02:57
  • @Sam That's the lifetime issue: a variable that you allocate in the automatic storage (AKA "stack variable") become invalid as soon as they go out of scope. Data in the dynamic storage, on the other hand, can outlive the scope of a variable pointing to it. – Sergey Kalinichenko Oct 05 '12 at 02:57
  • Thanks for the explanation. – Natasha Aug 30 '15 at 16:39
6

Because your array is stack allocated. Moving from Java to C++, you have to be very careful about the lifetime of objects. In Java, everything is heap allocated and is garbage collected when no references to it remain.

Here however, you define a stack allocated array a, which is destroyed when you exit the function getArray. This is one of the (many) reasons vectors are preferred to plain arrays - they handle allocation and deallocation for you.

#include <vector>

std::vector<int> getArray() 
{
    std::vector<int> a = {1, 2, 3};
    return a;
}
Yuushi
  • 25,132
  • 7
  • 63
  • 81
1

There are two places in memory that variables can go: the stack and the heap. The stack contains local variables created in methods. The heap holds other variables upon other conditions, like static variables.

When you create a in GetArray() that was a local variable stored on the stack and a was a pointer to that location. When the method returned the pointer, that layer of the stack was released (including the actual values that the pointer was pointing to).

Instead, you need to dynamically allocate the array, then the values will be in the heap which is not cleared when a function returns and a will point to them there.

int * GetArray() {
  int* a = new int[3];
  a[0] = 1;
  a[1] = 2;
  a[2] = 3;
  cout << endl << "Verifying 1" << endl;
  for (int ctr = 0; ctr < 3; ctr++)
    cout << a[ctr] << endl;
  return a;
}

Now you're passing around the address of those ints to and from functions while the values all sit in the heap where they aren't released until the end of the program or (preferably) you delete them.

Corey Ogburn
  • 24,072
  • 31
  • 113
  • 188
  • How does C++ know what to put in the heap and what to put in the stack. Isn't the curly brace notation just syntactic sugar for the explicit element by element array assignment shown here? – charmoniumQ Oct 05 '12 at 03:39
  • There are rules for what goes where depending on how the memory is allocated. The curly brace notation is not dynamically allocated so it goes in the stack. At compile time that space is set for the array. What I have will allocate that space at runtime and the contents are stored in the heap. – Corey Ogburn Oct 05 '12 at 13:30