70

Hi I am a newbie to C++ I am trying to return a 2d array from a function. It is something like this

int **MakeGridOfCounts(int Grid[][6])
{
  int cGrid[6][6] = {{0, }, {0, }, {0, }, {0, }, {0, }, {0, }};

  return cGrid;
}
Hunter McMillen
  • 59,865
  • 24
  • 119
  • 170
user1047092
  • 1,481
  • 4
  • 17
  • 18
  • 1
    And your question is? Is this C or C++? – Mat Dec 23 '11 at 15:25
  • 7
    If you're a newbie and are trying to return a 2D array, you may need [better learning material](http://stackoverflow.com/q/388242/46642). Arrays are not beginner-friendly, and even less when they are multidimensional. – R. Martinho Fernandes Dec 23 '11 at 15:29
  • 2
    Here is the [C version of the same question](http://stackoverflow.com/questions/8617889/return-a-2d-array-from-a-function). – Michael Kristofik Dec 23 '11 at 16:00
  • 1
    @MichaelKristofik Is it wise to mix the techniques of these two languages though? It may lead to huge compiling problems. C and C++ are not the same language. – gonidelis Mar 26 '19 at 22:10

10 Answers10

63

This code returns a 2d array.

 #include <cstdio>

    // Returns a pointer to a newly created 2d array the array2D has size [height x width]

    int** create2DArray(unsigned height, unsigned width)
    {
      int** array2D = 0;
      array2D = new int*[height];
    
      for (int h = 0; h < height; h++)
      {
            array2D[h] = new int[width];
    
            for (int w = 0; w < width; w++)
            {
                  // fill in some initial values
                  // (filling in zeros would be more logic, but this is just for the example)
                  array2D[h][w] = w + width * h;
            }
      }
    
      return array2D;
    }
    
    int main()
    {
      printf("Creating a 2D array2D\n");
      printf("\n");
    
      int height = 15;
      int width = 10;
      int** my2DArray = create2DArray(height, width);
      printf("Array sized [%i,%i] created.\n\n", height, width);
    
      // print contents of the array2D
      printf("Array contents: \n");
    
      for (int h = 0; h < height; h++)
      {
            for (int w = 0; w < width; w++)
            {
                  printf("%i,", my2DArray[h][w]);
            }
            printf("\n");
      }
    
          // important: clean up memory
          printf("\n");
          printf("Cleaning up memory...\n");
          for (int h = 0; h < height; h++) // loop variable wasn't declared
          {
            delete [] my2DArray[h];
          }
          delete [] my2DArray;
          my2DArray = 0;
          printf("Ready.\n");
    
      return 0;
    }
setller
  • 43
  • 7
Software_Designer
  • 8,490
  • 3
  • 24
  • 28
17

A better alternative to using pointers to pointers is to use std::vector. That takes care of the details of memory allocation and deallocation.

std::vector<std::vector<int>> create2DArray(unsigned height, unsigned width)
{
   return std::vector<std::vector<int>>(height, std::vector<int>(width, 0));
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • @R Sahu I have tried your code above, but I am getting this error: "error: unexpected ':' in nested name specifier; did you mean '::'?". See here: http://coliru.stacked-crooked.com/a/ef3e0c0a22c303ee – Timothée HENRY Jun 24 '19 at 14:17
  • @tucson, yes, of course :) That was a typo. Let me fix it. – R Sahu Jun 24 '19 at 14:30
  • I think it will make a local 2d vector and when the function returns it, the 2d vector will be copied which is often a catastrophe – Mohammed Samir May 24 '22 at 15:16
10

That code isn't going to work, and it's not going to help you learn proper C++ if we fix it. It's better if you do something different. Raw arrays (especially multi-dimensional arrays) are difficult to pass correctly to and from functions. I think you'll be much better off starting with an object that represents an array but can be safely copied. Look up the documentation for std::vector.

In your code, you could use vector<vector<int> > or you could simulate a 2-D array with a 36-element vector<int>.

Michael Kristofik
  • 34,290
  • 15
  • 75
  • 125
7

What you are (trying to do)/doing in your snippet is to return a local variable from the function, which is not at all recommended - nor is it allowed according to the standard.

If you'd like to create a int[6][6] from your function you'll either have to allocate memory for it on the free-store (ie. using new T/malloc or similar function), or pass in an already allocated piece of memory to MakeGridOfCounts.

Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
  • @user1047092 Yes, don't forget to `free` the allocated memory when you are done with it, or `delete` (if you are writing C++ as the title of this question says). – Filip Roséen - refp Dec 23 '11 at 16:02
  • 1
    No, if you're using C++ don't `delete` anything. Ever. Always use a resource-managing class. – Puppy Dec 23 '11 at 16:08
  • 2
    @DeadMG ... if he allocates memory, he should `delete` it. I don't care if you are all over heels in love with resource-managing classes, an allocation should follow by a deallocation. – Filip Roséen - refp Dec 23 '11 at 16:12
  • After I return it, how should I delete it ? it is already out of scope. – user1047092 Dec 23 '11 at 16:15
  • 1
    @user1047092 You `delete` it in the calling function after it's done with it. – Filip Roséen - refp Dec 23 '11 at 16:17
  • @Puppy what does that class do then? – Mulperi Jul 26 '20 at 18:59
  • @Mulperi Just because Windows can modify its own system files doesn't mean random programs should have that power. The same principle applies here; the implementation of the system has way more time and money spent on it and is written by far more experienced programmers than most regular programs, so they are far more likely to not screw up. Re-using their efforts is far wiser than doing it yourself and failing miserably. – Puppy Jul 27 '20 at 14:44
4

The function returns a static 2D array

const int N = 6;
int (*(MakeGridOfCounts)())[N] {
 static int cGrid[N][N] = {{0, }, {0, }, {0, }, {0, }, {0, }, {0, }};
 return cGrid;
}

int main() {
int (*arr)[N];
arr = MakeGridOfCounts();
}

You need to make the array static since it will be having a block scope, when the function call ends, the array will be created and destroyed. Static scope variables last till the end of program.

3
#include <iostream>
using namespace std ;

typedef int (*Type)[3][3] ;

Type Demo_function( Type ); //prototype

int main (){
    cout << "\t\t!!!!!Passing and returning 2D array from function!!!!!\n"

    int array[3][3] ;
    Type recieve , ptr = &array;
    recieve = Demo_function( ptr ) ;

    for ( int i = 0 ;  i < 3 ; i ++ ){
        for ( int j = 0 ; j < 3 ; j ++ ){
            cout <<  (*recieve)[i][j] << " " ;
        }
    cout << endl ; 
    }

return 0 ;
}


Type Demo_function( Type array ){/*function definition */

    cout << "Enter values : \n" ;
    for (int i =0 ;  i < 3 ; i ++)
        for ( int j = 0 ; j < 3 ; j ++ )
            cin >> (*array)[i][j] ;

    return array ; 
}
ahmad
  • 31
  • 2
1

Whatever changes you would make in function will persist.So there is no need to return anything.You can pass 2d array and change it whenever you will like.

  void MakeGridOfCounts(int Grid[][6])
    {
      cGrid[6][6] = {{0, }, {0, }, {0, }, {0, }, {0, }, {0, }};

    }

or

void MakeGridOfCounts(int Grid[][6],int answerArray[][6])
    {
     ....//do the changes in the array as you like they will reflect in main... 
    }
Nirav Patel
  • 339
  • 2
  • 4
1
int** create2DArray(unsigned height, unsigned width)
{
     int** array2D = 0;
     array2D = new int*[height];

     for (int h = 0; h < height; h++)
     {
          array2D[h] = new int[width];

          for (int w = 0; w < width; w++)
          {
               // fill in some initial values
               // (filling in zeros would be more logic, but this is just for the example)
               array2D[h][w] = w + width * h;
          }
     }

     return array2D;
}

int main ()
{

    printf("Creating a 2D array2D\n");
    printf("\n");

    int height = 15;
    int width = 10;
    int** my2DArray = create2DArray(height, width);
    printf("Array sized [%i,%i] created.\n\n", height, width);

    // print contents of the array2D
    printf("Array contents: \n");

    for (int h = 0; h < height; h++)
    {
         for (int w = 0; w < width; w++)
         {
              printf("%i,", my2DArray[h][w]);
         }
         printf("\n");
    }

    return 0;
}
cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
user3785412
  • 1,099
  • 2
  • 7
  • 3
  • 2
    You answer had two big drawbacks: 1. You only give code without explanation, and 2. your code formatting was wrong so that the markdown didn't recognize it as a code block. For proper formatting, you need four spaces indentation for each line of code. Note that you can add these four spaces by selecting your code and then clicking on the codeblock button in the editior (the one with the braces `{}`). I fixed that for you. The missing explanation is yours to give. Ps: I did not downvote. – cmaster - reinstate monica Mar 30 '15 at 17:52
  • How is this answer not a copy/paste of the one by Software_Designer below? – Matt Oct 11 '17 at 19:39
  • This is a copy of the code snippet by Software_Designer. – Daniel Mar 22 '18 at 16:10
1

returning an array of pointers pointing to starting elements of all rows is the only decent way of returning 2d array.

1

I would suggest you Matrix library as an open source tool for c++, its usage is like arrays in c++. Here you can see documention.

Matrix funcionName(){

    Matrix<int> arr(2, 2);

    arr[0][0] = 5;
    arr[0][1] = 10;
    arr[1][0] = 0;
    arr[1][1] = 44;

    return arr;
}
Amir Fo
  • 5,163
  • 1
  • 43
  • 51