views:

59

answers:

2

It's been a long time since I worked with C++, but I have a class that uses 3-dimensional data and I can't figure out how I can make this work. I need the sizes of the dimensions to be defined in the constructor. I tried this in the header:

class CImage
{
public:
    float values[][][];
...
}

and this in the constructor:

CImage::CImage(int cols, int rows, int depth)
{
    values[cols][rows][depth];
}

but this returns the error: "declaration of `values' as multidimensional array must have bounds for all dimensions except the first".

Also using this in the constructor does not work:

values = new float[cols][rows][depth];

I also tried using vector, but without much success. Header:

vector<vector<vector<float> > > values;

Nothing in constructor. No compiler errors, but when I try to set a value:

values[c][r][d] = value;

the program crashes.

It seems so basic, but I just can't figure it out...

+3  A: 

The program crashes when accessing that vector because it is empty, i.e. there are no elements at those indexes.

The best way to go about this is to make a linear, one-dimensional, vector (or even an array), and access it with a pair of operator()'s, see C++FAQ Lite for details. Or use boost::multi_array.

For example:

#include <vector>
#include <iostream>
class CImage
{
        int X, Y, Z;
        std::vector<float> values;
public:
        CImage(int cols, int rows, int depth)
                : X(cols), Y(rows), Z(depth),
                values(cols*rows*depth) {}
        float operator()(int x, int y, int z) const
        {
                return values[Z*Y*x + Z*y + z];
                // or you lay it out differently in memory
                // if you please, transparent to the user:
                // return values[x + X*y + X*Y*z];
        }
        float& operator()(int x, int y, int z)
        {
                return values[Z*Y*x + Z*y + z];
                // likewise, in a different layout
                // return values[x + X*y + X*Y*z];
        }
};

int main()
{
        CImage ci(3,3,3);
        ci(2,2,2) = 7.0;
        std::cout << ci(2,2,2) << '\n';
}
Cubbi
if you use `operator[]` it looks even better
swegi
@swegi: Yes, I was sanity-checking myself.
Cubbi
In the constructor, at the line where it says values(rows*cols*depth); my compiler gives me this error: no match for call to `(std::vector<float, std::allocator<float> >) (int)'. Does this have something to do with the way I write my constructor? Your notation gets lots of red underlining from my IDE.
RemiX
@RemiX: tested with MSVC 2010 on Windows, gcc 4.4.4 on Linux, Sun C++ 5.8 on Solaris. What IDE/compiler are you using?
Cubbi
Using Netbeans 6.8, with MinGW32 compiler. I tried creating a local vector<float> v1 in the constructor and it would accept the (rows*cols*depth) parameter, but the values property defined in the header won't.
RemiX
@RemiX: Oh, I see, you must have written `values(rows*cols*depth);` on a line of its own. That's a syntax error, yes. Members should be initalized before the opening brace of the constructor, but if you want to do that within the constructor body, write `values.resize(rows*cols*depth);`
Cubbi
Ah, seems that I made a mistake with a for-loop that made the index go out of bounds. The line values = vector<float>(rows*cols*depth); works, just like the line values.resize(rows*cols*depth); Thanks a lot!
RemiX
+1  A: 
DyP