9

in C++ I want to initialize a double matrix (2-dimensional double array) like I would normally do without pointers like so:

    double data[4][4] = {
    1,0,0,0,
    0,1,0,0,
    0,0,1,0,
    0,0,0,1
};

However, since I want to return and pass it to functions, I need it as a double** pointer. So, basically I need to initialize data in a nice way (as above), but then afterwards I need to save the pointer to the 2D-array without losing the data when the function exits.

Any help on this? :-)

Swaroop
  • 1,219
  • 3
  • 16
  • 32
Felix
  • 8,385
  • 10
  • 40
  • 59
  • 4
    Why do you need it as a `double**` ? What's wrong with a `double (*)[4]` ? – CB Bailey Aug 24 '10 at 07:16
  • This is C++. Can this be a class, with this array as a member, which passes a reference back when you call a member function? – Merlyn Morgan-Graham Aug 24 '10 at 07:23
  • possible duplicate of [Passing two-dimensional array via pointer](http://stackoverflow.com/questions/3515045/passing-two-dimensional-array-via-pointer) It's C, not C++, but it's exactly the same issue. – CB Bailey Aug 24 '10 at 07:28
  • None of the answers have hit bulls eye. I found out I can do this: double ** d = new double[4][4]; But, how will I initialize the value without the chore of writing code like: d[0][0] = 1; d[0][1] = 0;... – Felix Aug 24 '10 at 08:24
  • No, you can't. For example, g++ refuses to compile your snippet: `error: cannot convert 'double (*)[4]' to 'double**' in initialization`. – fredoverflow Aug 24 '10 at 13:58

7 Answers7

10

Unless you are particular about pointers, I would prefer a reference here

void init( double (&r)[4][4]){
    // do assignment
    r[0][0] = 1;
}

int main(){
    double data[4][4] = {
        1,0,0,0,
        0,1,0,0,
        0,0,1,0,
        0,0,0,1
    };

    init(data);
}

By the way, if you pass it to a function in this manner, you would be "assigning" rather than "initializing".

Alberto Chiusole
  • 2,204
  • 2
  • 16
  • 26
Chubsdad
  • 24,777
  • 4
  • 73
  • 129
6

Are all your matrices 4x4? Then I would simply define a class with a double[4][4] member and pass objects of that class around:

class Matrix
{
    double m[4][4];
    // ...
};

void function(const Matrix& matrix)
{
    // ...
}

If you need matrices of various dimensions, but they are known at compile time, use a template:

template <size_t n>
class Matrix
{
    double m[n][n];
    // ...
};

template <size_t n>
void function(const Matrix<n,n>& matrix)
{
    // ...
}

This saves you from dealing with array-to-pointer decay and makes the code more readable IMHO.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
6

First, declaration of the double dimensional array is not correct. It needs to be done as follows:

double data[4][4] = {  
        {1.0,0,0,0},  
        {0,1,0,0},  
        {0,0,1,0},  
        {0,0,0,1}  
    };

Second, for passing it in a function you can do it like

show(data);

In the function declaration, you need to give the argument as an array with giving all dimensions except the first. So the declaration would look like:

void show(double arr[][4])
{
   ...
   ...
}

This passes the array as a reference wihout you needing to use a pointer.

Hope this helped.

3

double (*)[4] is very different from double **

Just sketch the layout of your doubles in the memory for both and you should understand why you can't use them interchangeably.

Didier Trosset
  • 36,376
  • 13
  • 83
  • 122
  • since I don't know or understand "double (*)[4]", I can't sketch it. What does it mean? – Felix Aug 24 '10 at 07:51
1

How about this (with pointers, and does what you asked for)

#include <iostream>

using namespace std;

int refer(double (*a)[4])
{
   cout<<"First value is "<<(*a)[0];
   (*a)[0] = 37;
   cout<<"changed value is "<<(*a)[0];
}

int main()
{
   double data[4][4] = {
    1.0,0,0,
    0,1,0,0,
    0,0,1,0,
    0,0,0,1
   };
   refer(data);
   return 0;
}
SandBag_1996
  • 1,570
  • 3
  • 20
  • 50
1

Initialize temporary variable in this way and then copy it to the dynamically allocated memory.

Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
0

late to the party, but.... c++ is meant to work with c++ stl. (At least according to Bjarne Stroustrup if you're using raw pointers in c++ then you're doing something wrong.)

#include <array> // on top
// ..    

std::array<std::array<int, 4>, 4> data {{
    {1,0,0,0},
    {0,1,0,0},
    {0,0,1,0},
    {0,0,0,1}
}};

// access it normally 

data[1][2] = 123;
std::cout << data[0][0]; // prints 1. (#include <iostream>)

// You can return std::array from a function as a normal return value, don't worry it is not going to be reallocated, or missing.

std::array<std::array<int, 4>, 4> give_me_data() {
  std::array<std::array<int, 4>, 4> data {{
    {1,0,0,0},
    {0,1,0,0},
    {0,0,1,0},
    {0,0,0,1}
  }};
  return data;
}

(works with Mac's XCode, also gcc supports it https://stackoverflow.com/a/12616826/1031191)

What's the benetif? It works nicely with std algorithms, knows its size, same performance, etc. ref: std::array vs array performance

Barney Szabolcs
  • 11,846
  • 12
  • 66
  • 91