C++ functions returning arrays

19,210

Solution 1

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

Solution 2

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.

Solution 3

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.

Share:
19,210
charmoniumQ
Author by

charmoniumQ

Updated on June 04, 2022

Comments

  • charmoniumQ
    charmoniumQ almost 2 years

    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
    charmoniumQ over 11 years
    I thought C++ has no trash collection? Or is this more of a scope/lifetime issue?
  • Corey Ogburn
    Corey Ogburn over 11 years
    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.
  • Sergey Kalinichenko
    Sergey Kalinichenko over 11 years
    @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.
  • charmoniumQ
    charmoniumQ over 11 years
    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?
  • Corey Ogburn
    Corey Ogburn over 11 years
    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.
  • Natasha
    Natasha over 8 years
    Thanks for the explanation.