Search code examples
c++arraysinitializationinitializer-list

How to initialize a C++ object member that is an 2D array of integers


I have a class (foo) that has a member (c) that I want to be a two-dimensional array of integers. For some reason I can't get the initializer list to work properly on the array.

49:  class foo{
50:  public: 
51:    int a;
52:    int b;
53:    int** c;
54:    foo(int a_arg, int b_arg, int** c_arg) : a(a_arg),b(b_arg), c(c_arg)
55:    {}
56:  };//end of class
57:  
58:  int main() {
59:    foo bar{5,7, {{1,2,3},{4,5,6},{7,8,9}}  };
60:  }

I have found a lot of member initializer list examples online, but none that specifically deal with a class member that happens to be a C style array (all examples I found seemed to use std::vector or similar). But please note that this code is going to run in an embedded environment which doesn't support the use of any of the C++ standard template library classes (so no vectors or similar).

If I write this code with just a_arg and b_arg it works fine. But when I add in c_arg I get the following error message from the compiler.

src/main.cpp:54:3: note: candidate constructor not viable: cannot convert initializer list argument to 'int ** ' foo(int a_arg, int b_arg, int** c_arg) : a(a_arg),b(b_arg), c(c_arg)

It looks like the type of {{1,2,3},{4,5,6},{7,8,9}} is not int**. But if it's not that then what is it? I have tried adding various type modifiers onto the definitions of c and c_arg but none of them seem to work.

If the third argument is a variable of type int** then it does compile. But I don't get the initil values like I want.

class foo{
  public: 
  int a;
  int b;
  int** c;
  foo(int a_arg, int b_arg, int** c_arg) : a(a_arg),b(b_arg), c(c_arg)
  {}
};//end of class

int main() {
  int** xxx = (int**)malloc(9*sizeof(int));
  foo bar{5,7, xxx  };
}

Solution

  • As mentioned in the compiler error, {{1,2,3},{4,5,6},{7,8,9}} is an 'initializer list' and not an array. Also int** c is not a two-dimensional array of integers but an pointer to an array of integer pointers. To get what you want you could do something like this in your main function:

        int main() {
        
          int  data[] = {1,2,3,4,5,6,7,8,9};
          int* arr2d[] = { &data[0], &data[3], &data[6] };
        
          foo bar{5,7, arr2d };
        
          std::cout << arr2d[1][1]; // will print 5
        
        }
    

    Also note that int** xxx = (int**)malloc(9*sizeof(int)); is not correct either. You are creating a pointer somewhere in the memory with space for 9 ints, but you are then casting that to an array of 9 int pointers.

    Alternatively, if you know that the bound on the second dimension of your array will always be 3 then you could do this:

    class foo{
    public: 
      int a;
      int b;
      int (*c)[3];
      foo(int a_arg, int b_arg, int (*c_arg)[3]) : a(a_arg),b(b_arg), c(c_arg)
      {}
    };
    
    int main() {
    
      int arr2d[][] = { {1,2,3}, {4,5,6}, {7,8,9} };
      foo bar{ 5, 7, arr2d };
    
      std::cout << data[1][1];
    
    }