-2

I am trying to pass a 2d array to a function. I don't want the actual array to be modified. So pass it by value. But my actual 2darray is getting modified.(when i modify myArray, x is getting modified). Why is it so?

int main(int argc, const char* argv[])
{
    int x[3][3];
    x[0][0]=2;
    x[0][1]=2;
    x[0][2]=2;
    x[1][0]=2;
    x[1][1]=2;
    x[1][2]=2;
    x[2][0]=2;
    x[2][1]=2;
    x[2][2]=2;
    func1(x);
}

void func1(int myArray[][3])
{
    int i, j;
    int ROWS=3;
    int COLS=3;

     for (i=0; i<ROWS; i++)
     {
         for (j=0; j<COLS; j++)
         {
             myArray[i][j] =3;
         }
     }
}

And is it possible to pass a 2D array by value if we don't know both dimensions?.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • 1
    C-style arrays are not copyable or assignable, but you can pass an `std::vector`, or make a local copy of an array passed by reference. – juanchopanza Aug 11 '14 at 08:49
  • Arrays decays to pointer when passed to a function – quantdev Aug 11 '14 at 08:49
  • This isn't possible. An array is passed as a pointer. – sapi Aug 11 '14 at 08:50
  • 1
    @sapi But you can write the function such that it accepts an array by reference instead of a pointer. What is not possible is to pass it by value. – juanchopanza Aug 11 '14 at 08:51
  • 2
    Trying to write a program that works both as C and C++ is hard work. I suggest you choose 1 language and stick with it. – pmg Aug 11 '14 at 08:52
  • `void func1(int myArray[][3])` : `myArray` is pointer. However, you can pass that array wrapped by a structure . – BLUEPIXY Aug 11 '14 at 09:00
  • @juanchopanza Thanks for d reply. But how can I make a local copy of a 2d array whose size is not known in advance? Sorry if the question is too silly. I am really new to C – user3852475 Aug 11 '14 at 09:05
  • @user3852475 It depends what you mean by "not known". In your example, the size is known at compile time. You can use that information (see my answer). If it is only known at runtime, you have to pass it to the function (or use a type such as `std::vector`, which knows its own size.) – juanchopanza Aug 11 '14 at 09:10
  • I gave the dimension for better readability of the code. And it was misleading. Sorry for d mistake. thanks again for your reply. I found solution for my problem from the answer given by @angel Kohn. – user3852475 Aug 11 '14 at 09:31

4 Answers4

1

You can take advantage of the fact that arrays in user defined types are copied and assigned when instances of that type are copied or assigned, for example

template <size_t N, size_t M>
struct Foo
{
  int data[N][M];
};

template <size_t N, size_t M>
void func1(Foo<N, M> foo)
{
  foo.data[1][2] = 42;
}

int main()
{
  Foo<3, 3> f;
  f.data[0][0]=2;
  ...
  func1(f);
}

Here, func1 has a local copy of the foo, which has its own copy of the array. I have used templates to generalize to arbitrary sizes.

Note that C++ provides the std::array template, which you could use instead of Foo, so in real code you would do something like this:

#include <array>

template <typename T, size_t N, size_t M>
void func1(std::array<std::array<T, N>, M> arr)
{
  arr[1][2] = 42;
}

int main()
{
  std::array<std::array<int, 3>, 3> a;
  a[0][0]=2;
  ...
  func1(a);
}

If you are stuck with pre-C++11 implementations, you can use either std::tr1::array (header <tr1/array> or boost::array from the boost library. It is also a nice exercise to roll out your own.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
0

An array is passed as a pointer, and it is not very C++`ish to pass 2d arrays as pointer. You should a class to encapsulate the array and pass a reference to that class.

This way the "user" doesn't know of the underlying implementation of your array as well and you can change it without affecting functionality later on. And of course passing a const reference to a class instance will be as lightweight as passing pointers, hence there will be no performance impact.

Max Shifrin
  • 809
  • 9
  • 24
0

In standard C++, section 8.3.5 Functions point 5 explains that:

After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively.

This is why your function works in fact with a pointer and modifies the original value.

Point 8 explains further that:

If the type of a parameter includes a type of the form “array of runtime bound of T”, “pointer to array of unknown bound of T”, or “reference to array of unknown bound of T”, the program is ill-formed.

So, you have to know the size in advance.

Alternative:

If you'd like to work by value, better use standard containers, such as vectors (here, vector<vector<int>>). Your x would then be declared in main() with:

vector<vector<int>> x(3, vector<int>(3));  // initialised vector of 3 vector of 3 ints

or even better, to get rid of your long list of assignments to the same constant:

vector<vector<int>> x(3, vector<int>(3, 2));  // vector of 3 vector of 3 ints with value 2

And your function be defined as:

void func1(vector<vector<int>> myArray)
{   // resets all existing values to 3.  
    for (size_t i = 0; i<myArray.size(); i++)
        for (size_t j = 0; j<myArray[i].size(); j++)
            myArray[i][j] = 3;
}  
Christophe
  • 68,716
  • 7
  • 72
  • 138
0

to prevent func1 from being changed, change it to a const pointer.

void func1(const int (*myArray)[3])
{
    int i, j;
    int ROWS=3;
    int COLS=3;

     for (i=0; i<ROWS; i++)
     {
         for (j=0; j<COLS; j++)
         {
            // myArray[i][j] =3; //compilation error, is now const
            cout <<" "<<myArray[i][j];  
         }
     }
}
Angel Koh
  • 12,479
  • 7
  • 64
  • 91
  • @user3852475 But in your question, you want to modify the array in the function, so this would obviously not work. – juanchopanza Aug 11 '14 at 09:33
  • @juanchopanza I pass the array to the function as myArray. then make a copy of that with myArray as const pointer. then modify the copy. Thank u for your valuable replies. – user3852475 Aug 11 '14 at 09:37