简体   繁体   中英

C++ Avoiding Triple Pointers

I am trying to create an array of X pointers referencing matrices of dimensions Y by 16. Is there any way to accomplish this in C++ without the use of triple pointers?

Edit: Adding some context for the problem.

There are a number of geometries on the screen, each with a transform that has been flattened to a 1x16 array. Each snapshot represents the transforms for each of number of components. So the matrix dimensions are 16 by num_components by num_snapshots , where the latter two dimensions are known at run-time. In the end, we have many geometries with motion applied.

I'm creating a function that takes a triple pointer argument, though I cannot use triple pointers in my situation. What other ways can I pass this data (possibly via multiple arguments)? Worst case, I thought about flattening this entire 3D matrix to an array, though it seems like a sloppy thing to do. Any better suggestions?

What I have now:

function(..., double ***snapshot_transforms, ...)

What I want to accomplish:

function (..., <1+ non-triple pointer parameters>, ...)

Below isn't the function I'm creating that takes the triple pointer, but shows what the data is all about.

static double ***snapshot_transforms_function (int num_snapshots, int num_geometries)
{
    double component_transform[16];

    double ***snapshot_transforms = new double**[num_snapshots];

    for (int i = 0; i < num_snapshots; i++)
    {
        snapshot_transforms[i] = new double*[num_geometries];

        for (int j = 0; j < num_geometries; j++)
        {
            snapshot_transforms[i][j] = new double[16];

            // 4x4 transform put into a 1x16 array with dummy values for each component for each snapshot
            for (int k = 0; k < 16; k++)
                snapshot_transforms[i][j][k] = k;
        }
    }

    return snapshot_transforms;
}

Edit2: I cannot create new classes, nor use C++ features like std, as the exposed function prototype in the header file is getting put into a wrapper (that doesn't know how to interpret triple pointers) for translation to other languages.

Edit3: After everyone's input in the comments, I think going with a flattened array is probably the best solution. I was hoping there would be some way to split this triple pointer and organize this complex data across multiple data pieces neatly using simple data types including single pointers. Though I don't think there is a pretty way of doing this given my caveats here. I appreciate everyone's help =)

It is easier, better, and less error prone to use an std::vector . You are using C++ and not C after all. I replaced all of the C-style array pointers with vector s. The typedef doublecube makes it so that you don't have to type vector<vector<vector<double>>> over and over again. Other than that the code basically stays the same as what you had.

If you don't actually need dummy values I would remove that innermost k loop completely. reserve will reserve the memory space that you need for the real data.

#include <vector>

using std::vector; // so we can just call it "vector"
typedef vector<vector<vector<double>>> doublecube;

static doublecube snapshot_transforms_function (int num_snapshots, int num_geometries)
{    
    // I deleted component_transform. It was never used

    doublecube snapshot_transforms;
    snapshot_transforms.reserve(num_snapshots);

    for (int i = 0; i < num_snapshots; i++)
    {
        snapshot_transforms.at(i).reserve(num_geometries);

        for (int j = 0; j < num_geometries; j++)
        {
            snapshot_transforms.at(i).at(j).reserve(16);

            // 4x4 transform put into a 1x16 array with dummy values for each component for each snapshot
            for (int k = 0; k < 16; k++)
                snapshot_transforms.at(i).at(j).at(k) = k;
        }
    }

    return snapshot_transforms;
}

Adding a little bit of object-orientation usually makes the code easier to manage -- for example, here's some code that creates an array of 100 Matrix objects with varying numbers of rows per Matrix. (You could vary the number of columns in each Matrix too if you wanted to, but I left them at 16):

#include <vector>
#include <memory>  // for shared_ptr (not strictly necessary, but used in main() to avoid unnecessarily copying of Matrix objects)

/** Represents a (numRows x numCols) 2D matrix of doubles */
class Matrix
{
public:
   // constructor
   Matrix(int numRows = 0, int numCols = 0)
      : _numRows(numRows)
      , _numCols(numCols)
   {
      _values.resize(_numRows*_numCols);
      std::fill(_values.begin(), _values.end(), 0.0f);
   }

   // copy constructor
   Matrix(const Matrix & rhs)
      : _numRows(rhs._numRows)
      , _numCols(rhs._numCols)
   {
      _values.resize(_numRows*_numCols);
      std::fill(_values.begin(), _values.end(), 0.0f);
   }

   /** Returns the value at (row/col) */
   double get(int row, int col) const {return _values[(row*_numCols)+col];}

   /** Sets the value at (row/col) to the specified value */
   double set(int row, int col, double val) {return _values[(row*_numCols)+col] = val;}

   /** Assignment operator */
   Matrix & operator = (const Matrix & rhs)
   {
      _numRows = rhs._numRows;
      _numCols = rhs._numCols;
      _values  = rhs._values;
      return *this;
   }

private:
   int _numRows;
   int _numCols;
   std::vector<double> _values;
};

int main(int, char **)
{
   const int numCols = 16;
   std::vector< std::shared_ptr<Matrix> > matrixList;
   for (int i=0; i<100; i++) matrixList.push_back(std::make_shared<Matrix>(i, numCols));

   return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM