Reputation: 13
Request for a sanity check ...
I am storing a 3D matrix in a 1D array as follows:
double * myVector = new double[NCHANNELS*NROWS*NCOLUMNS];
I want to be able to access myVector using [channel][row][column] syntax, so I am creating a C++ reference:
double (& my3dMatrix)[NCHANNELS][NROWS][NCOLUMNS] = myVector;
Have I used the proper syntax here, i.e., will
my3dMatrix[channel][row][column]
return
*(myVector + channel*NROWS*NCOLUMNS + row*NCOLUMNS + column)?
Thanks.
Upvotes: 1
Views: 144
Reputation: 96906
Yes, you can do it. But your reference initializator is missing type cast and dereference operator, it will not even compile. It should be:
double (& my3dMatrix)[NCHANNELS][NROWS][NCOLUMNS] =
*(double (*)[NCHANNELS][NROWS][NCOLUMNS])myVector;
If you're using C++11/14, you can use this fancy syntax instead:
double (& my3dMatrix)[NCHANNELS][NROWS][NCOLUMNS] =
*(decltype(&my3dMatrix))myVector;
double (& my3dMatrix)[NCHANNELS][NROWS][NCOLUMNS] =
*reinterpret_cast<double (*)[NCHANNELS][NROWS][NCOLUMNS]>(myVector);
or C++11 version:
double (& my3dMatrix)[NCHANNELS][NROWS][NCOLUMNS] =
*reinterpret_cast<decltype(&my3dMatrix)>(myVector);
Syntax explanation
When you initialize a reference, you can only use initializator of a certain type. This type must match the type reference refers to.
double (& my3dMatrix)[NCHANNELS][NROWS][NCOLUMNS] = expression;
In this case you need expression
to be double [NCHANNELS][NROWS][NCOLUMNS]
.
myVector
can't be used here because it's a pointer to array and my3dMatrix
is a reference to an array. Ok, then we need to deference operator.
But *myVector
does not work either. It's double [NCHANNELS*NROWS*NCOLUMNS]
but we need double [NCHANNELS][NROWS][NCOLUMNS]
. You want to tell the compiler than he should assume that myVector
is pointing to another type before dereferencing it. In these cases you need a type cast.
The way you write them is (type)expression
and reinterpret_cast<type>(expression)
.
(First one came from C language. Second one is one of the modern C++ casts. There are 4 of them, each one have a specific purpose. C-style cast does the same and can be used instead of all 4. C++-style ones are used by some guys because they think that these casts are more readable. I personally consider them too bulky and use old one.)
So, here is your reference initialization:
double (& my3dMatrix)[NCHANNELS][NROWS][NCOLUMNS] =
* (double (*)[NCHANNELS][NROWS][NCOLUMNS]) myVector;
^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^
dereference C-style type cast expression
Compiler trusts you and assumes that myVector is a double (*)[NCHANNELS][NROWS][NCOLUMNS]
. After dereferncing it becomes double [NCHANNELS][NROWS][NCOLUMNS]
- the type you need.
Now, about that decltype
trick. (It was added in 2011, so old compilers don't support it.) decltype(expression)
is replaced by the compiler with the type of expression
. For example, decltype(1)
means int
. decltype(my3dMatrix)
means double [NCHANNELS][NROWS][NCOLUMNS]
. But you need another type, because you can't cast pointer to 1D array to 3D array. You can cast it to pointer to 3D array instead. When you want address of something, you use &
. So, you need decltype(&my3dMatrix)
. You can assume it means (double (&*)[NCHANNELS][NROWS][NCOLUMNS])
, but there is no such thing as pointer to reference, so it becomes just (double (*)[NCHANNELS][NROWS][NCOLUMNS])
.
double (& my3dMatrix)[NCHANNELS][NROWS][NCOLUMNS] =
* (decltype(&my3dMatrix)) myVector;
^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^
dereference C-style type cast expression
I hope you understood it.
Upvotes: 3